kuroの覚え書き

96の個人的覚え書き

Flask2.0.0(3.0.0)のBlueprintの使い方

Flask1系から2系にアップデートしたとき、blueprintの使い方がちょっと変わっていてトラブったので覚書。


manage.py   ## 2系以降は不要
sqlite.db
app----------+
             |-__init__.py
             |-config.py
             |-models.py
             |-views---------+
             |               |-home.py
             |               |-tools.py
             |
             |-templates-----+
             |               |-index.html
             |               |.........
             |-static           

こういう構成だとして
1系のときは
__init__.py

from flask import Flask

app = Flask(__name__)
app.config.from_object('app.config')

中略

#Blueprint
from app.views import home, tools
                    
app.register_blueprint(home.app)
app.register_blueprint(tools.app)

app/home.py

from functools import wraps
from flask import request, redirect, url_for, render_template, flash, g, Blueprint
from flask import session as fl_session
from ..models import User
from app import app, Session
import sys
sys.setrecursionlimit(100000)

app = Blueprint('home', __name__)

################################################################################
def login_required(f):
	@wraps(f)
	def decorated_view(*args, **kwargs):
		if g.user is None:
			return redirect(url_for('login', next=request.path))
		return f(*args, **kwargs)
	return decorated_view

@app.before_request
def load_user():
	user_id = fl_session.get('user_id')
	if user_id is None:
		g.user = None
	else:
		g.user = Session().query(User).get(fl_session['user_id'])

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

@app.errorhandler(500)
def internal_server_error(e):
	return render_template('500.html'), 500

##############################################################################
#アプリルート
@app.route('/')
def index():
	return render_template('index.html')
##############################################################################
#ログイン・アウト管理
@app.route('/login', methods=['GET', 'POST'])
def login():
	if request.method == 'POST':
		user, authenticated = User.authenticate(Session().query, request.form['email'], request.form['password'])
		if authenticated:
			fl_session['user_id'] = user.id
			flash('You were logged in')
			return redirect(url_for('index'))
		else:
			flash('Invalid email or password')
	return render_template('login.html')

@app.route('/logout')
def logout():
	fl_session.pop('user_id', None)
	flash('You were logged out')
	return redirect(url_for('index'))

このような感じであったが、
2系以降では

__init__.py

from flask import Flask

app = Flask(__name__)
app.config.from_object('app.config')

中略

#Blueprint
from app.views.home import home_bp
from app.views.tools import tools_bp

app.register_blueprint(home_bp)
app.register_blueprint(tools_bp)

home.py

from functools import wraps
from flask import request, redirect, url_for, render_template, flash, g, Blueprint
from flask import session as fl_session
from ..models import User
from app import app, Session
import sys
sys.setrecursionlimit(100000)

home_bp = Blueprint('home', __name__)

################################################################################
def login_required(f):
	@wraps(f)
	def decorated_view(*args, **kwargs):
		if g.user is None:
			return redirect(url_for('home.login', next=request.path))
		return f(*args, **kwargs)
	return decorated_view

@home_bp.before_request
def load_user():
	user_id = fl_session.get('user_id')
	if user_id is None:
		g.user = None
	else:
		g.user = Session().query(User).get(fl_session['user_id'])

@home_bp.errorhandler(404)
def page_not_found(e):
	return render_template('404.html'), 404

@home_bp.errorhandler(500)
def internal_server_error(e):
	return render_template('500.html'), 500

##############################################################################
#アプリルート
@home_bp.route('/')
def index():
	return render_template('index.html')
##############################################################################
#ログイン・アウト管理
@home_bp.route('/login', methods=['GET', 'POST'])
def login():
	if request.method == 'POST':
		user, authenticated = User.authenticate(Session().query, request.form['email'], request.form['password'])
		if authenticated:
			fl_session['user_id'] = user.id
			flash('You were logged in')
			return redirect(url_for('home.index'))
		else:
			flash('Invalid email or password')
	return render_template('login.html')

@home_bp.route('/logout')
def logout():
	fl_session.pop('user_id', None)
	flash('You were logged out')
	return redirect(url_for('home.index'))

このようになる。
一度書き換えてしまえばこの方が分類がはっきりしてわかりやすい書き方になっていると思う。1系の書き方ではappがあっちにもこっちにも出てきて繋がりが分かりにくかったので。

1系の書き方のままでも2系の大方の動作には問題がないのだが、Loginまわりが軒並み動かなくなるので、書き換えたほうがいいと思う。おそらくurl_forの書き方が変わっているのが原因だと思う。

なお2系ではFlask_scriptによる python manage.py runserverによる起動はできないので、manage.pyは使わない。flask runコマンドで起動する。