less than 1 minute read

Flask를 모듈화 하여 사용할때 Blueprint를 쓴다.

Basic usage

yourapp/
    __init__.py
    admin/
        __init__.py
        views.py
        static/
        templates/
    home/
        __init__.py
        views.py
        static/
        templates/
    control_panel/
        __init__.py
        views.py
        static/
        templates/
    models.py

이런 식의 구조로 원하는 부분만을 모듈화 하여 별개의 폴더로 구성할 수 있다. 폴더 안에 init.py 파일을 넣어두면 마치 패키지 처럼 import 하여 사용하면 된다.

code1

# facebook/views/profile.py

from flask import Blueprint, render_template

profile = Blueprint('profile', __name__,
                    template_folder='templates',
                    static_folder='static')

@profile.route('/<user_url_slug>')
def timeline(user_url_slug):
    # Do some stuff
    return render_template('profile/timeline.html')

@profile.route('/<user_url_slug>/photos')
def photos(user_url_slug):
    # Do some stuff
    return render_template('profile/photos.html')

@profile.route('/<user_url_slug>/about')
def about(user_url_slug):
    # Do some stuff
    return render_template('profile/about.html')

이런 식으로 파일 구성을 하면 된다. Blueprint 라는 클래스를 생성하고 그 안에 사용할 폴더를 넣는다.

# facebook/__init__.py

from flask import Flask
from .views.profile import profile

app = Flask(__name__)
app.register_blueprint(profile)

Using a dynamic URL prefix

prefix는 두 가지 방법으로 지정 가능하다

# facebook/views/profile.py

from flask import Blueprint, render_template

profile = Blueprint('profile', __name__, url_prefix='/<user_url_slug>')

# [...]
# facebook/__init__.py

from flask import Flask
from .views.profile import profile

app = Flask(__name__)
app.register_blueprint(profile, url_prefix='/<user_url_slug>')

top level 에서 모듈 이동을 용이하게 하기 위해선 registration에 prefix를 주는것이 좋다고 한다. (아래)

그러면 code1을 아래와 같이 적을 수 있다. (짧은 endpoint)

# facebook/views/profile.py

from flask import Blueprint, render_template, g

from ..models import User

# The prefix is defined on registration in facebook/__init__.py.
profile = Blueprint('profile', __name__)

@profile.url_value_preprocessor
def get_profile_owner(endpoint, values):
    query = User.query.filter_by(url_slug=values.pop('user_url_slug'))
    g.profile_owner = query.first_or_404()

@profile.route('/')
def timeline():
    return render_template('profile/timeline.html')

@profile.route('/photos')
def photos():
    return render_template('profile/photos.html')

@profile.route('/about')
def about():
    return render_template('profile/about.html')

아래는 아직 이해 못함
We’re using the g object to store the profile owner and g is available in the Jinja2 template context.
This means that for a barebones case all we have to do in the view is render the template.
The information we need will be available in the template.


{# facebook/templates/profile/photos.html #}

{% extends "profile/layout.html" %}

{% for photo in g.profile_owner.photos.all() %}
    <img src="{{ photo.source_url }}" alt="{{ photo.alt_text }}" />
{% endfor %}

Updated: