웹서비스 기술 익히기 - flask 기본 사용법

2. flask 기본 사용법

1. Flask 모듈 임포트 (보통 다음과 같이 임포트)

  • pip install flask
In [1]:
from flask import Flask

2. Flask 객체를 app에 할당

In [3]:
app = Flask(__name__)                  

3. app 객체를 이용해 라우팅 경로를 설정

4. 해당 라우팅 경로로 요청이 올 때 실행할 함수를 바로 밑에 작성해야 함

  • 해당 웹페이지에 대한 경로를 URI로 만들어준다고 이해하자


In [4]:
@app.route("/")
def hello():                           
    return "<h1>Hello World!</h1>"

5. 메인 모듈로 실행될 때 플라스크 서버 구동 (서버로 구동한 IP 와 포트를 옵션으로 넣어줄 수 있음)

In [5]:
host_addr = "0.0.0.0"
port_num = "8080"
In [6]:
if __name__ == "__main__":              
    app.run(host=host_addr, port=port_num)
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
127.0.0.1 - - [21/Nov/2017 20:00:03] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/Nov/2017 20:00:03] "GET /favicon.ico HTTP/1.1" 404 -

한번에 작성하면 다음과 같은 코드가 됩니다.

In [6]:
from flask import Flask

app = Flask(__name__)
@app.route("/hello")
def hello():                           
    return "<h1>JaeSung Fighting</h1>"

if __name__ == "__main__":              
    app.run(host="127.0.0.1", port="8080")
 * Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
127.0.0.1 - - [04/Apr/2018 21:35:22] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [04/Apr/2018 21:35:30] "GET /hello HTTP/1.1" 200 -
  • flask 라이브러리를 사용한 코드는 보통 파일이름.py 로 작성한 후
    • python 파일이름.py
  • 위와 같이 서버에서 실행하는 것이 일반적
  • 노트북에서는 실행 후, 테스트 끝나면, Terminate를 눌러줘야 함


라우팅

  • 복잡한 URI를 함수로 쉽게 연결하는 방법 제공
In [8]:
from flask import Flask

app = Flask(__name__)
@app.route("/")
def hello():                           
    return "<h1>Hello World!</h1>"

@app.route("/hello")
def hello_flask():
    return "<h1>Hello Flash!</h1>"

@app.route("/first")
def hello_first():
    return "<h3>Hello First</h3>"

if __name__ == "__main__":              
    app.run(host="0.0.0.0", port="8080")
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
127.0.0.1 - - [21/Nov/2017 20:06:08] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/Nov/2017 20:06:11] "GET /first HTTP/1.1" 200 -

이해하고 실습하기

http://0.0.0.0:8080/first 로 접속시, h3 태그로 Hello First! 출력하기

In [18]:
@app.route("/profile/<username>")
def get_profile(username):
    return "profile: " + username
In [10]:
from flask import Flask

app = Flask(__name__)
@app.route("/")
def hello():                           
    return "<h1>Hello World!</h1>"

@app.route("/profile/<username>")
def get_profile(username):
    return "profile: " + username

@app.route("/first/<username>")
def get_first(username):
    return "<h3>Hello " + username + "!</h3>"

if __name__ == "__main__":              
    app.run(host="0.0.0.0", port="8080")
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
127.0.0.1 - - [04/Apr/2018 21:39:30] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [04/Apr/2018 21:39:36] "GET /profile/1 HTTP/1.1" 200 -


이해하고 실습하기

http://0.0.0.0:8080/first/userid 로 접속시, h3 태그로 Hello userid ! 출력하기

  • URI를 변수로 사용, 변수에 데이터 타입도 줄 수 있음
    • 데이터 타입이 없으면 문자열로 인식
    • int 이외에 float 도 데이터 타입으로 줄 수 있음
    • 다음 코드 추가 후, http://0.0.0.0:8080/message/1 접속
In [ ]:
@app.route("/message/<int:message_id>")
def get_message(message_id):
    return "message id: " + message_id
In [12]:
from flask import Flask

app = Flask(__name__)
@app.route("/")
def hello():                           
    return "<h1>Hello World!</h1>"

@app.route("/message/<int:message_id>")
def get_message(message_id):
    return "message id: %d" % message_id

@app.route("/first/<int:messageid>")
def get_first(messageid):
    return "<h1>%d</h1>" % (messageid + 5)


if __name__ == "__main__":              
    app.run(host="0.0.0.0", port="8080")
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
127.0.0.1 - - [21/Nov/2017 20:15:12] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/Nov/2017 20:15:16] "GET /first/1 HTTP/1.1" 200 -

이해하고 실습하기

http://0.0.0.0:8080/first/숫자 로 접속시, h1 태그로 숫자 + 5 출력하기

특정 함수를 호출하는 URI 찾기

In [13]:
from flask import Flask, url_for
app = Flask(__name__)

@app.route("/hello/")
def hello():                           
    return "<h1>Hello World!</h1>"

@app.route("/profile/<username>")
def get_profile(username):
    return "profile: " + username

if __name__ == "__main__":              
    with app.test_request_context():
        print(url_for('hello'))
        print(url_for('get_profile', username='flash'))
    # app.run(host="0.0.0.0", port="8080")
/hello/
/profile/flash


REST API 구현해보기

  • 특정한 URI를 요청하면 JSON 형식으로 데이터를 반환하도록 만들면 됨
  • 즉, 웹주소(URI) 요청에 대한 응답(Response)를 JSON 형식으로 작성
  • Flask에서는 dict(사전) 데이터를 응답 데이터로 만들고, 이를 jsonify() 메서드를 활용해서 JSON 응답 데이터로 만들 수 있음
In [1]:
from flask import Flask, jsonify
app = Flask(__name__)
  • data를 사전 데이터로 만들고, 이를 jsonify() 메서드에 넣어서 return 해주면 됨
In [2]:
@app.route('/json_test')
def hello_json():
    data = {'name' : 'Aaron', 'family' : 'Byun'}
    return jsonify(data)

@app.route('/server_info')
def server_json():
    data = { 'server_name' : '0.0.0.0', 'server_port' : '8080' }
    return jsonify(data)
In [ ]:
if __name__ == "__main__":              
    app.run(host="0.0.0.0", port="8080")
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
127.0.0.1 - - [25/Apr/2018 20:15:15] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [25/Apr/2018 20:15:15] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [25/Apr/2018 20:15:22] "GET /server_info HTTP/1.1" 200 -

이해하고 실습하기

http://0.0.0.0:8080/server_info 로 접속시,

{ 'server_name' : '0.0.0.0', 'server_port' : '8080' }

JSON으로 리턴하기

In [17]:
from flask import Flask, jsonify
app = Flask(__name__)

@app.route('/server_info')
def hello_json():
    data = {'server_name' : '0.0.0.0', 'server_port' : '8080'}
    return jsonify(data)

if __name__ == "__main__":              
    app.run(host="0.0.0.0", port="8080")
    
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
127.0.0.1 - - [21/Nov/2017 20:22:19] "GET / HTTP/1.1" 404 -
127.0.0.1 - - [21/Nov/2017 20:22:24] "GET /server_info HTTP/1.1" 200 -


PyCharm 에디터 설치해보기

  • 웹서비스 구현을 위해, 노트북 이외의 에디터를 활용해보기

다음 코드부터 04_flask_practices 디렉토리에 저장 (Pycharm 으로 해당 코드 파일 표기)

POST/GET method 구현해보기 (Pycharm: 04_flask_practices/method_html.py)

  • POST/GET 요청으로 받는 url은 아래와 같이 구현됨
In [14]:
from flask import Flask, redirect, url_for, request
app = Flask(__name__)

@app.route('/success/<name>')
def success(name):
   return 'welcome %s' % name

@app.route('/login', methods = ['POST', 'GET'])
def login():
   if request.method == 'POST':
      user = request.form['myName']
      return redirect(url_for('success', name=user))
   else:
      user = request.args.get('myName')
      return redirect(url_for('success', name=user))

if __name__ == '__main__':
    app.run(host="0.0.0.0", port="8080")
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
127.0.0.1 - - [04/Apr/2018 21:42:23] "GET / HTTP/1.1" 404 -
[2018-04-04 21:42:27,724] ERROR in app: Exception on /login [GET]
Traceback (most recent call last):
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "<ipython-input-14-162560149c14>", line 15, in login
    return redirect(url_for('success', name=user))
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/helpers.py", line 333, in url_for
    return appctx.app.handle_url_build_error(error, endpoint, values)
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/app.py", line 1805, in handle_url_build_error
    reraise(exc_type, exc_value, tb)
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/flask/helpers.py", line 323, in url_for
    force_external=external)
  File "/Users/coupang/anaconda/lib/python3.6/site-packages/werkzeug/routing.py", line 1768, in build
    raise BuildError(endpoint, values, method, self)
werkzeug.routing.BuildError: Could not build url for endpoint 'success'. Did you forget to specify values ['name']?
127.0.0.1 - - [04/Apr/2018 21:42:27] "GET /login HTTP/1.1" 500 -
127.0.0.1 - - [04/Apr/2018 21:43:12] "GET /login?myName=Dave HTTP/1.1" 302 -
127.0.0.1 - - [04/Apr/2018 21:43:12] "GET /success/Dave HTTP/1.1" 200 -

테스트1: https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop

  • Set POST
  • Set Address -> 0.0.0.0:8080/login
  • Set Body - form-data -> key / value (myName / dave)
  • Click Send

테스트2: HTML 코드와 연계해서 생각해보기 (Pycharm: 04_flask_practices/templates/login.html)



In [ ]:
<!DOCTYPE html>
<html>
   <body>

      <form action = "http://0.0.0.0:8080/login" method = "get">
         <p>Enter Name:</p>
         <p><input type = "text" name = "myName" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>

   </body>
</html>

웹페이지 구현 - HTML (Pycharm: 04_flask_practices/simple_html.py)

  • 특정 웹주소(URI)를 접속하면 웹페이지를 보여주면 됨
  • 서버는 요청을 받아, 적절한 처리를 한뒤 html을 반환함
In [23]:
from flask import Flask, render_template
app = Flask(__name__)
In [24]:
@app.route('/html_test')
def hello_html():
    # html file은 templates 폴더에 위치해야 함
    return render_template('simple.html')
  • 04_flask_practices/simple.html
In [ ]:
if __name__ == "__main__":              
    app.run(host="0.0.0.0", port="8080")
이해하고 실습하기