===================== 4. Flaskを使いこなす1 ===================== Flaskrにユーザー管理画面と認証処理を追加しながら進めていきます。 Flask公式のチュートリアルではユーザーログイン処理がありますが、 config.pyに記述したユーザーのみになっています。 今回はユーザーを追加・編集・削除できるような画面を作成し、 そのユーザーを使ってログインできるようにしましょう。 4.1 ユーザーログイン処理を追加する1 =================================== **samples/04/01を参考にして下さい** ユーザークラスの追加 ---------------------- models.pyにUserクラスを追加します。 ここでは、emailとpasswordでログインするユーザーを作ります。 flaskr/models.py .. literalinclude:: ../samples/04/01/flaskr/models.py データベースの作成 ------------------ つくったらデータベースを初期しておきましょう。 しかし、いちいちpythonインタプリタから初期化するのは面倒なので、 コマンドラインから作成できるようにしておきましょう。 まずは、Flaks-Scriptプラグインをインストールします。:: echo Flask-Script >> requirements.txt pip install Flask-Script 次にmanage.pyを変更します。 manage.py .. literalinclude:: ../samples/04/01/manage.py 作成したらデータベースを作成しなおしましょう。:: rm flaskr/flaskr.db python manage.py init_db ユーザー用のビューを追加 ------------------------ ユーザーを管理するためのページをベースを作りましょう。 views.pyに追加していきます。 .. literalinclude:: ../samples/04/01/flaskr/views.py * routeのパラメータ * int: 整数 * float: 浮動小数点 * path: 文字列(スラッシュも受け取る) * HTTP method * GET * HEAD * POST * PUT * DELETE * OPTIONS 実行してみましょう ------------------ manage.pyを変更したので、今後は以下のコマンドで起動します。:: python manage.py runserver 4.2 ユーザーログイン処理を追加する2 ==================================== **samples/04/02を参考にして下さい** ユーザー管理画面を作っていきます。 ユーザー作成 /users/create の追加 --------------------------------- flaskr/views.py:: from flaskr.models import Entry, User ... @app.route('/users/create/', methods=['GET', 'POST']) def user_create(): if request.method == 'POST': user = User(name=request.form['name'], email=request.form['email'], password=request.form['password']) db.session.add(user) db.session.commit() return redirect(url_for('user_list')) return render_template('user/edit.html') flaskr/templates/user/edit.html .. literalinclude:: ../samples/04/02/flaskr/templates/user/edit.html ユーザー一覧 /users/ の追加 --------------------------- flaskr/views.py:: @app.route('/users/') def user_list(): users = User.query.all() return render_template('user/list.html', users=users) flaskr/templates/user/list.html .. literalinclude:: ../samples/04/02/flaskr/templates/user/list.html ユーザー一覧 /users// の追加 ----------------------------------------- flaskr/views.py:: @app.route('/users//') def user_detail(user_id): user = User.query.get(user_id) return render_template('user/detail.html', user=user) flaskr/templates/user/detail.html .. literalinclude:: ../samples/04/02/flaskr/templates/user/detail.html ユーザー一覧 /users//edit/ の追加 ------------------------------------------------ flaskr/views.py:: from flask import request, redirect, url_for, render_template, flash, abort ... @app.route('/users//edit/', methods=['GET', 'POST']) def user_edit(user_id): user = User.query.get(user_id) if user is None: abort(404) if request.method == 'POST': user.name=request.form['name'] user.email=request.form['email'] user.password=request.form['password'] db.session.add(user) db.session.commit() return redirect(url_for('user_detail', user_id=user_id)) return render_template('user/edit.html', user=user) ユーザー一覧 /users//delete/ の追加 ------------------------------------------------ flaskr/views.py:: from flask import request, redirect, url_for, render_template, flash, abort, \ jsonify ... @app.route('/users//delete/', methods=['DELETE']) def user_delete(user_id): user = User.query.get(user_id) if user is None: response = jsonify({'status': 'Not Found'}) response.status_code = 404 return response db.session.delete(user) db.session.commit() return jsonify({'status': 'OK'}) 実行してみましょう ------------------ :: python manage.py runserver 4.3 ユーザーログイン処理を追加する3 =================================== **samples/04/03を参考にして下さい** さらにモクモクと作っていきましょう。 ログイン画面の追加 ------------------ flaskr/views.py:: from flask import request, redirect, url_for, render_template, flash, abort, \ jsonify, session ... @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': user, authenticated = User.authenticate(db.session.query, request.form['email'], request.form['password']) if authenticated: session['user_id'] = user.id flash('You were logged in') return redirect(url_for('show_entries')) else: flash('Invalid email or password') return render_template('login.html') @app.route('/logout') def logout(): session.pop('user_id', None) flash('You were logged out') return redirect(url_for('show_entries')) flaskr/templates/login.html .. literalinclude:: ../samples/04/03/flaskr/templates/login.html flaskr/templates/layout.html .. literalinclude:: ../samples/04/03/flaskr/templates/layout.html ログインしないと記事を追加できないように変更します。 flaskr/templates/show_entries.html .. literalinclude:: ../samples/04/03/flaskr/templates/show_entries.html 実行してみましょう ------------------ :: python manage.py runserver 4.4 ユーザー管理画面は認証していない人には見せたくない ====================================================== **事前にユーザーを作ってからやらないと・・・ログインできなくなりますw** ユーザー管理画面など一般ユーザーには見せたくないページがあります。 先ほど作成したユーザー管理画面を、ログインしないと見れないように変更します。 flaskr/views.py:: from functools import wraps from flask import request, redirect, url_for, render_template, flash, abort, \ jsonify, session, g ... 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 = session.get('user_id') if user_id is None: g.user = None else: g.user = User.query.get(session['user_id']) ... @app.route('/users/') @login_required def user_list(): ... @app.route('/users//') @login_required def user_detail(user_id): ... @app.route('/users//edit/', methods=['GET', 'POST']) @login_required def user_edit(user_id): ... @app.route('/users/create/', methods=['GET', 'POST']) @login_required def user_create(): ... @app.route('/users//delete/', methods=['DELETE']) def user_delete(user_id): * before_request * routeで追加したendpointの前に呼ばれる。 * beforeがあるということは、afterもある。 * session['user_id']に格納したuser.idからUserを取得 * gというFlaskインスタンス内のグローバルのような変数にuserを追加 * login_required * デコレータを定義 * g.userを確認してログインしているかをチェックしている。 書き換えたviews.pyはこちら .. literalinclude:: ../samples/04/03/flaskr/views.py 実行してみましょう ------------------ :: python manage.py runserver ログイン処理ができました。なんとなくそれっぽくなりましたね。