질문이 있으십니까?

기본 컨텐츠 및 사용자가 직접 참여하여 만들어진 다양한 내용을 검색합니다.

웹서버 Flask

web development, one drop at a time. 웹개발, 한번에 한방울.

설치 및 기본구조 만들기

# 모듈설치
$> pip install flask

# 기본 구조 폴더 만들기
$> mkdir webapp
  /helloflask
    - /static
      - /css
      - /images
      - /js
    - /templates
    - __init__.py
  start_helloflask.py

__init__.py

# 파일경로: helloflask/__init__.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def helloworld():
  return "Hello Flask World!"

start_helloflask.py

# 파일경로 : helloflask/start_helloflask.py
from helloflask import app

app.run(host='0.0.0.0')

첫 실행

> python start_helloflask.py
 * Serving Flask app "helloflask" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [26/Jul/2020 20:22:00] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [26/Jul/2020 20:22:00] "GET /favicon.ico HTTP/1.1" 404 -
[ 그림. 웹브라우저에서 첫 실행 결과 화면 ]

Global Object : g

from flask import g

app = Flask(__name__)
app.debug = True # use only debug!

@app.before_request
def before_request():
  print("before_request!!!")
  g.str = "한글"

@app.route("/")
def helloflask():
  return "Hello Flask!" + getattr(g, 'str', '111')

Response Objects

from flask import Response, make_response

# http://127.0.0.1:5000
@app.route("/")
def helloflask():
    # return make_response("custom response")
    # response_class
    custom_res = Response("Custom Response", 200, {'test': 'ttt'})
    return make_response(custom_res) # 스트리밍 응답

Response Object (Cont'd) : WSGI

from flask import make_response

# WSGI(WebServer Gateway Interface)
# http://127.0.0.1/test_wsgi
@app.route('/test_wsgi')
def wsgi_test():
    def application(environ1, start_response1):
        body = 'The request method waw %s' % environ1['REQUEST_METHOD']
        headers = [ ('Content-Type', 'text/plain'),
                    ('Content-Length', str(len(body)))]
        start_response1('200 OK', headers)
        return [body]
    return make_response(application)

Request Event Handler

@app.before_first_request
def before_first_request():
    print("before first request: 앱 기동하고 맨처음 요청만 응답")

@app.before_request
def before_request():
    print("before_request: 매 요청마다 실행")

@app.after_request
def after_request(response):
    return("after_request: 매 요청 처리되고 나서 실행") # print문만 있으면 오류남

@app.teardown_request
def teardown_request(exception):
    return("teardown_request: 브라우저가 응답하고 실행") # print문만 있으면 오류남

@app.teardown_appcontext
def teardown_appcontext(exception):
    print("teardown_appcontext: HTTP 요청 애플리케이션 컨텍스트가 종료될 때 실행")
    #이거하면 메모리에서 서비스가 안내려가는 현상 발생

Routing

@app.route('/test')
def ...

@app.route('/test', method=['POST','PUT'])
def ...

# http://127.0.0.1:5000/test/100
@app.route('/test/<tid>')
def test_tid(tid):
  print("tid is", tid)
  return("tid %s" % tid)

# http://127.0.0.1:5000/test/100/200
@app.route('/test/<tid>/<bid>')
def test_tid_bid(tid,bid):
    return("/test tid is %s, bid is %s" % (tid, bid))

@app.route('/test/', defaults={'page': 'index.html'})
def movepage(page):
    return render_template(page)

@app.route('/test', host='abc.com') # host옵션은 주지마세요.
@app.route('/test', redirect_to='/new_test') # route('/new_test')로 이동

Routing (Cont'd) : subdomain

# local.com:5000 만 받겠다.
app.config['SERVER_NAME'] = 'local.com:5000'

@app.route("/")
def helloworld_local():
  return "Hello Local.com!"

@app.route("/", subdomain="gw")
def helloworld():
  return "Hello G.Local.com!!!"

Request Parameter

# MultiDict Type
... get('<param name>', <default-value>, <type>)
methods: get, getlist, clear, etc

from flask import request

# GET
request.args.get('p')

# 예제) http://127.0.0.1:5000/rp?q=123
@app.route("/rp")
def rp():
    q = request.args.get('q')
    return "q is %s" % str(q) #q값은 딕셔너리이므로 str처리

# POST
request.form.get('p', 123)

# GET or POST
request.values.get('v')

# Parameters
request.args.getlist('qs')

# 예제) http://127.0.0.1:5000/rp?q=123&q=abc
@app.route("/rp")
def rp():
    return str(request.args.getlist('q'))
    # ['123', 'abc']

Request Parameter Custom Function Type

from datetime import datetime, date

def ymd(fmt):
    def trans(date_str):
        # strftime: 시간을 문자열로 출력
        # strptime: 문자열을 시간으로 만들때
        return datetime.strptime(date_str, fmt)
    return trans

# http://127.0.0.1:5000/dt
# http://127.0.0.1:5000/dt?date=2020-01-01
@app.route('/dt')
def dt():
    tmp = request.values.get('date',date.today())
    datestr = request.values.get('date', tmp, type=ymd('%y-%m-%d'))
    return "우리나라 시간형식:" + str(datestr)

request.environ

# http://127.0.0.1:5000/environ
@app.route("/environ")
def environ():
    return ('REQUEST_METHOD: %(REQUEST_METHOD) s') % request.environ

return ('REQUEST_METHOD: %(REQUEST_METHOD) s <br>'
    'SCRIPT_NAME: %(SCRIPT_NAME) s <br>'
    'PATH_INFO: %(PATH_INFO) s <br>'
    'QUERY_STRING: %(QUERY_STRING) s <br>'
    'SERVER_NAME: %(SERVER_NAME) s <br>'
    'SERVER_PORT: %(SERVER_PORT) s <br>'
    'SERVER_PROTOCOL: %(SERVER_PROTOCOL) s <br>'
    'wsgi.version: %(wsgi.version) s <br>'
    'wsgi.input: %(wsgi.input) s <br>'
    'wsgi.errors: %(wsgi.errors) s <br>'
    'wsgi.multithread: %(wsgi.multithread) s <br>'
    'wsgi.multiprocess: %(wsgi.multiprocess) s <br>'
    'wsgi.run_once: %(wsgi.run_once) s') % request.environ

Ajax request

app.config.update(MAX_CONTENT_LENGTH=1024*1024)

# http://127.0.0.1:5000/ajax
@app.route("/ajax")
def ajax():
    # return request.endpoint # URI 부분을 말함
    # return str(request.get_json()) # 넘어온 json값
    return str(request.max_content_length)

Response Object

from flask import Response

# Response Attributes
  - headers
  - status
  - status_code
  - data
  - mimetype

# http://127.0.0.1:5000/response
@app.route("/response")
def response():
    res = Response("Test") # 인스턴스 생성
    res.headers.add('Program-Name', 'Test Response')
    res.set_data("This is Test Program")
    res.set_cookie("User Token", "xxxxx")
    return res

Cookie

from flask import Response

# Cookie __init__ Arguments
  - key
  - value
  - max_age
  - expires
  - domain
  - path

ex)
res = Response("Test")
res.set_cookie("UserToken", "A128c9")

# other request
request.cookies.get('UserToken', 'default token')

# http://127.0.0.1:5000/setcookie
@app.route("/setcookie")
def setcookie():
    res = Response("쿠키값을 만들었습니다.") # 인스턴스 생성
    res.set_cookie("User Token", "xxxxx")
    return res

# http://127.0.0.1:5000/getcookie
@app.route("/getcookie")
def getcookie():
    tmp = request.cookies.get('shindalsoo', 'default value')
    return tmp

연습문제: Cookie

문제1) 다음 형태로 요청했을 때 해당 key로 Cookie를 굽는 코드를 작성하시오. (http://127.0.0.1:5000/wc?key=111&val=3333)

@app.route("/wc")
def wc():
    key = request.values.get("key")
    val = request.values.get("val")
    res = Response("쿠키값을 만들었습니다.") # 인스턴스 생성
    if key is not None:
        res.set_cookie("key", key)
    if val is not None:
        res.set_cookie("val", val)
    return res

문제2) 다음과 같이 요청했을 때 해당 key의 Cookie Value를 출력하는 코드를 작성하시오. (http://127.0.0.1:5000/rc?key=token)

Session

from flask import session
from datetime import timedelta

app.secret_key = 'X1243yRH!mMwf'

또는,

app.config.update(
  SECRET_KEY='X1243yRH!mMwf',
  SESSION_COOKIE_NAME='pyweb_flask_session',
  PERMANENT_SESSION_LIFETIME=timedelta(31) # 31일
)

* Save to Memory, File or DB

Session (Cont'd)

from flask import session

@app.route('/setsess')
def setsess():
  session['Token'] = '123X'
  return "Session이 설정되었습니다."

@app.route('/getsess')
def getsess():
    if session.get('Token'):
        return "세션값은" + session.get('Token')
    else:
        return "세션값이 없습니다."

@app.route('/delsess')
def delsess():
  if session.get('Token'):
    del session['Token']
  return "Session이 삭제되었습니다."

댓글을 작성하세요

문서 이력

  • 2020-06-14 날짜로 신달수 님으로 부터 컨텐츠명이 변경 되었습니다.
  • 2020-07-26 날짜로 신달수 님께서 수정 작업을 하였습니다.
  • 2020-07-26 날짜로 신달수 님께서 등록 작업을 하였습니다.
  • 2020-07-27 날짜로 신달수 님께서 수정 작업을 하였습니다.
  • 2020-07-28 날짜로 신달수 님께서 수정 작업을 하였습니다.
  • 2020-07-29 날짜로 신달수 님께서 수정 작업을 하였습니다.
  • 2020-08-02 날짜로 신달수 님께서 수정 작업을 하였습니다.
  • 2020-08-03 날짜로 신달수 님께서 수정 작업을 하였습니다.
  • 2020-08-03 날짜로 신달수 님께서 수정 작업을 하였습니다.
  • 2020-08-04 날짜로 신달수 님께서 수정 작업을 하였습니다.
  • 2020-08-05 날짜로 신달수 님께서 수정 작업을 하였습니다.