Flask doc (2)

JinWooHyun·2021년 1월 20일
0

Flask Documentation

목록 보기
1/2

라우팅

route() 데코레이터는 함수와 URL을 연결해준다.

@app.route(/) 
def index():
	return ‘Index Page’

@app.route(/hello’)
def hello():
	return ‘Hello World’

URL을 동적으로 구성할 수 있고, 함수에 여러 룰을 덧붙일수있다.

변수 규칙

<variable_name> 으로 URL에 특별한 영역으로 표시해야된다. 그 부분은 함수의 키워드 인수로써 넘어간다.

@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id
ValueDesc
intaccepts integers
floatlike int but for floating point values
pathlike the default but also accepts slashes

URL 생성

라우팅이 설정된 함수에 대한 URL을 얻어내기 위해 url_for() 함수를 사용하면 된다.

이 함수는 첫번째 인자로 함수의 이름과 URL 룰의 변수 부분에 대한 다수의 키워드를 인자로 받는다. 알수없는 인자는 쿼리 인자로 URL에 덧붙여진다.

>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
...  print url_for('index')
...  print url_for('login')
...  print url_for('login', next='/')
...  print url_for('profile', username='John Doe')
...
/
/login
/login?next=/
/user/John%20Doe
  1. URL역변환이 URL을 하드코딩하는것 보다 훨씬 설명적이다. 더 중요한것은, 이 방식은 전체적으로 URL이 어디있는지 기억할 필요없이 한번에 URL을 다 변경할 수 있다.

  2. URL을 얻어내는것은 특수 문자 및 유니코드 데이타를에 대한 이스케이핑을 명확하게 해주기때문에 여러분이 그것들을 처리할 필요가 없다.

  3. 작성한 어플케이션이 URL의 최상위 바깥에 위치한다면 (예를 들면,
    / 대신에 /myapplication), url_for() 가 그 위치를 상대적 위치로 적절하게 처리해줄것이다.

HTTP 메소드

기본적으로 GET 방식으로 제공되지만, route() 데코레이터에 methods 인자를 제공하면 다른 방식으로 변경할 수 있다.

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

HTTP Methods

GET
브라우저가 어떤 페이지에 저장된 정보를 단지 얻기 위해 서버에 요청하고 서버는 그 정보를 보낸다. 가장 일반적인 메소드다.

HEAD
브라우저가 어떤 페이지에 저장된 내용이 아니라 헤더라 불리는 정보를 요청한다. 어떤 어플리케이션이 GET 요청을 받은것 처럼 처리하나, 실제 내용이 전달되지 않는다. 하부에 있는 Werkzeug 라이브러리들이 그런 처리를 하기 때문에 플라스크에서는 그런 처리는 전혀 할 필요가 없다.

POST
브라우저는 서버에게 새로운 정보를 전송하도록 특정 URL에 요청하고 그 정보가 오직 한번 저장되는것을 보장하도록 한다. 이것이 보통 HTML폼을 통해서 서버에 데이터 전송하는 방식이다.

PUT
POST 와 유사하지만 서버가 오래된 값들을 한번 이상 덮어쓰면서 store procedure를 여러번 실행할 수 있다. 여러분이 이것이 유용한 이유를 물을수도 있지만, 몇가지 적당한 이유가 있다. 전송시 연결을 잃어버리는 경우는 생각해보면, 브라우저와 서버사이에서 정보의 단절없이 요청을 다시 안전하게 받을 수도 있다. POST 는 단 한번 요청을 제공하기 때문에 이런 방식은 불가능하다.

DELETE
주어진 위치에 있는 정보를 제거한다.

OPTIONS
클라이언트에게 요청하는 URL이 어떤 메소드를 지원하는지 알려준다. Flask 0.6부터 이 기능은 자동 구현된다.

정적 파일

동적인 웹 어플리케이션은 정적 파일을 필요로한다. 이상적으로 웹서버는 정적 파일들을 서비스하지만, 개발시에는 플라스크가 그 역할을 대신해준다.

정적파일에 대한 URL을 얻으려면, 특별한 static 끝점 이름을 사용해야한다

url_for('static', filename='style.css')

이 파일은 파일시스템에 static/style.css로 저장되어야한다.

템플릿 보여주기

템플릿을 뿌려주기 위해, render_template() 메소드를 사용할 수 있다. 템플릿의 이름과 템플릿에 보여줄 변수를 키워드 인자로 넘겨주면 된다.

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

Flask는 templates 폴더에서 템플릿을 찾는다.

Jinja2 Template Documentation 공식 문서

요청 데이터 접근하기

컨텍스트 로컬

pass

요청 객체

from flask import request

현재 요청 메소드는 method 속성으로 사용할 수 있다. 폼 데이타( HTTP POST 나 PUT 요청으로 전달된 데이타)에 접근하려면, form 속성을 사용할 수 있다.

@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'
    # 아래의 코드는 요청이 GET 이거나, 인증정보가 잘못됐을때 실행된다.
    return render_template('login.html', error=error)

URL로 넘겨진 파라미터 (?key=value)에 접근하려면, args 속성을 사용할 수 있다

searchword = request.args.get('key', '')

파일 업로드

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')
    ...

만약 서버에 저장되는 파일명을 클라이언트에서의 파일명을 그대로 사용하기를 원한다면, Werkzeug에서 제공하는 secure_filename() 함수에 그 파일명을 전달

from flask import request
from werkzeug import secure_filename

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

쿠키

Reading cookies

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.

Stroing cookies

from flask import make_response

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

리다이렉션과 에러

사용자가 다른 엔드포인트로 redirect하기 위해서는 redirect() 함수를 사용. 에러코드를 가지고 일찍 요청을 중단하기를 원한다면 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()

기본으로 하얀 화면에 검정 글씨의 에러 페이지가 각 에러코드를 위해 보여진다. 만약 에러페이지를 변경하기를 원한다면 errorhandler() 데코레이터를 사용할 수 있다

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

기본적으로 상태 코드는 200으로 반환된다.

응답에 관하여

view 함수로부터 반환되는 값은 자동으로 response 객체로 변환된다.

만약 뷰 안에서 결과 response 객체를 찾기를 원한다면 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

make_response() 함수를 사용하여 반환되는 표현을 래핑하고, 변경을 위해 결과 객체를 얻은 다음 반환하기만 하면 된다.

세션

Request object외에도 하나의 요청에서 다음 요청까지 사용자에 대한 구체적인 정보를 저장할 수 있는 session 이라는 객체가 있다. 세션은 쿠키 위에서 구현되어 지고 암호화를 사용하여 그 쿠키를 서명한다.

즉, 사용자는 쿠키의 내용을 볼 수는 있지만 서명을 위해 사용된 비밀키를 알지 못한다면 쿠키의 내용을 변경할 수 없다는 것을 의미한다.

세션을 사용하기 위해서는 비밀키를 설정해야 한다.

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form action="" method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))

# set the secret key.  keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

메세지 플래싱

메세지를 flash 하기 위하여 flash() 메소드를 사용하고 메세지를 가져오기 위하여 템플릿에서 사용할 수 있는 get_flashed_messages() 메소드를 사용할 수 있다.

메시지 플래싱(Message Flashing) 챕터

로깅

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

Logging documentation

WSGI 미들웨어에서 후킹하기

개발한 어플리케이션을 WSGI 미들웨어에 올리기를 원한다면, 내부 WSGI 어플리케이션을 래핑할 수 있다.

from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)
profile
Unicorn Developer

0개의 댓글