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コマンドで起動する。