Flask 공식문서 Quickstart 정리

yo·2021년 6월 13일
0

Flask 설치

pip install Flask

A Minimal Application

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
  • 실행
    export FLASK_APP=hello
    flask run

HTTP Methods

  • 디폴트는 GET이다. 다른 메서드를 사용하기 위해서는 메서드를 추가로 명시해야한다.
  • GET메서드가 있다면, 플라스크가 HEAD 메서드를 자동으로 지원한다. OPTIONS도 마찬가지.
예시1. HTTP 메서드 명시 안하면 GET만 작동함.
@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
예시2. 다른 HTTP 메서드를 사용하기 위해서는 추가로 명시해줘야 함.
from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return do_the_login()
    else:
        return show_the_login_form()

Static Files

  • 'static' 이라는 폴더를 프로젝트 폴더 안에 만들고 정적 파일을 이 안에 두면 플라스크가 자동으로 처리해준다. url은 /static을 써서 접근한다.
    아래 예시에서 style.css의 프로젝트 상 경로는 static/style.css가 된다.
    url_for('static', filename='style.css')

Rendering Templates

  • from flask import render_template를 통해 template를 return할 수 있다.
  • 템플릿은 'templates폴더 안에 두어야 한다.
  • 템플릿 렌더링은 flask가 디폴트로 제공하는 Jinja2 template engine을 통해 렌더링된다.
from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)
  • 프로젝트가 모듈구조인지, 페키지 구조인지에 따라 templates폴더를 어떻게 둘지가 달라진다. (아래 사진 참고)

The Request Object

  • 우선은 request를 import 해야한다.
    from flask import request
  • form데이터에 접근하려면 `request.form['key']
  • query string에 접근하려면 request.args.get('key', '')
  • Key가 없으면 KeyError가 난다. 이 경우 flask가 자동으로 HTTP 400 Bad Request를 내준다. 하지만 user-friendly하지 않기 때문에 직접 KeyError를 잡아 처리해주는 것이 좋다.
@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template('login.html', error=error)

File Uploads

-HTML form에 enctype="multipart/form-data"를 반드시 적어줘야만 한다. 적지 않으면 브라우저가 파일 전송 자체를 하지 않는다.

  • request타고 온 파일은 in memory 혹은 파일시스템의 임시 장소에 보관된다.
  • 이 파일에 files로 접근할 수 있다.
  • 각 파일은 dictionary형태로 저장된다.
  • 파일은 파이썬의 file object와 같이 취급되고, save() 메서드를 통해 서버의 파일시스템에 저장할 수 있다.
from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
  • client가 업로드 하기 전의 파일 이름을 알고 싶으면 filename속성으로 접근하며 ㄴ된다.
  • 다만 이 속성은 위조될 수 있기 때문에 절대 이 값을 신뢰하지 말것
  • 파일이름에 접근하고 싶다면 secure_filename()을 통해 접근해라. 이 함수는 Werkzeug(내장 라이브러리)가 제공한다.
from werkzeug.utils import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        file = request.files['the_file']
        file.save(f"/var/www/uploads/{secure_filename(f.filename)}")

Cookies

  • request 객체의 쿠키에 접근하려면:request.cookies.get('key')
  • response에 cookie를 심어주려면: `resp.set_cookie('key', 'value')``
from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.
from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

Redirects and Errors

  • abort는 raise exception과 비슷한 것 같다.
  • 바로 에러를 내뱉는다. 이때 400, 401같이 상태를 지정 가능하고, 플라스크가 에러 페이지를 자동으로 렌더해준다.
  • redirect는 redirect 메서드 이용하면 된다. 쉬움.
  • 아래 예시는 index함수가 login으로 redirect해주고, login에서는 abort시켜주는 예시.(실용성은 없고 예시를 위한 예시)
from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

About Responses

  • view function의 return 값은 자동으로 response object로 변환된다.
  • return값이 string이면 response body에 실리며, text/html mimetype이 된다.
  • return값이 dict면, jsonify()가 호출된다.
  • 플라스크가 return값을 reponse object로 바꾸는 로직은 다음과 같다.
1. If a response object of the correct type is returned it’s directly 2. returned from the view.
2. If it’s a string, a response object is created with that data and the default parameters.

3. If it’s a dict, a response object is created using jsonify.

4. If a tuple is returned the items in the tuple can provide extra information. Such tuples have to be in the form (response, status), (response, headers), or (response, status, headers). The status value will override the status code and headers can be a list or dictionary of additional header values.

5. If none of that works, Flask will assume the return value is a valid WSGI application and convert that into a response object.
  • view에서 response객체를 잡고 싶다면 make_response()를 사용하면 된다.
  • 첫 예시는 바로 response를 리턴한 것, 두번째 예시는 make_response()로 리스폰스 객체를 잡아 가공한 뒤 리턴하는 것.
from flask import render_template

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html'), 404
from flask import make_response

@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template('error.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

APIs with JSON

  • dict를 리턴하면 자동으로 JSON response가 된다.
@app.route("/me")
def me_api():
    user = get_current_user()
    return {
        "username": user.username,
        "theme": user.theme,
        "image": url_for("user_image", filename=user.image),
    }
  • dict외에 다른 데이터 타입을 JSON response로 보내려면 jsonify를 호출하면 된다.
from flask import jsonify

@app.route("/users")
def users_api():
    users = get_all_users()
    return jsonify([user.to_json() for user in users])

Sessions

당장 쓰지 않을 것 같아서 pass

Message Flashing

  • flash()를 통해 커스텀 메세지를 리턴할 수 있다는 것 같다.
  • 이것도 당장 쓰지 않을 것 같아서 pass

Logging
Hooking in WSGI Middleware
Using Flask Extensions

profile
Never stop asking why

0개의 댓글