フラスコメガチュートリアル、パート5:ユーザーログイン

翻訳者からの序文。

このマニュアルの前の部分は、wiygnによって翻訳されています。 彼の同意を得て、私はこの仕事を続けています。







これはシリーズの5番目の記事で、Flaskマイクロフレームワークを使用してPython Webアプリケーションを作成した経験を説明しています。









このガイドの目的は、かなり機能的なマイクロブログアプリケーションを開発することです。オリジナリティが完全に欠如しているため、マイクロブログアプリケーションと呼ぶことにしました。









目次
パート2:テンプレート

パート3:フォーム

パート4:データベース

パート5:ユーザーログイン (この記事)

パート6:プロフィールページとアバター

パート7:単体テスト

パート8:フォロワー、連絡先、友達

パート9:ページネーション

パート10:全文検索

パート11:メールサポート

パート12:再構成

パート13:日付と時刻

パート14:I18nおよびL10n

パート15:Ajax

パート16:デバッグ、テスト、およびプロファイリング

パート17:Linux(およびRaspberry Piでも)での展開

パート18:Heroku Cloudでのデプロイ





短い繰り返し



前のパートでは、データベースを作成し、それをユーザーと投稿で埋める方法を学びましたが、この機能はまだアプリケーションに実装されていません。 2章前に、Webフォームの作成方法とログインフォームの作成方法を学びました。









この記事では、Webフォームとデータベースに関する知識を組み合わせて、ユーザーログイン用のシステムを作成します。 このガイドの最後に、小さなアプリケーションが新しいユーザーを登録して承認します。









この章で作業するには、アプリケーションが前の章の最後に残したものと同じでなければなりません。 アプリケーションがインストールされ動作していることを確認してください。











構成



前の章と同様に、使用する拡張機能を設定することから始めます。 承認には、Flask-LoginとFlask-OpenIDの2つの拡張機能が必要です。 次のように設定しますapp/__init__.py











 import os from flask.ext.login import LoginManager from flask.ext.openid import OpenID from config import basedir lm = LoginManager() lm.init_app(app) oid = OpenID(app, os.path.join(basedir, 'tmp'))
      
      





Flask-OpenID拡張機能は、一時ファイルをどこかに保存する必要があります。そのため、初期化中に、 tmp



フォルダーへのパスが転送されます。









承認申請機能



ビュー関数app/views.py



)を更新しましょう:









 from flask import render_template, flash, redirect, session, url_for, request, g from flask.ext.login import login_user, logout_user, current_user, login_required from app import app, db, lm, oid from forms import LoginForm from models import User, ROLE_USER, ROLE_ADMIN @app.route('/login', methods = ['GET', 'POST']) @oid.loginhandler def login(): if g.user is not None and g.user.is_authenticated(): return redirect(url_for('index')) form = LoginForm() if form.validate_on_submit(): session['remember_me'] = form.remember_me.data return oid.try_login(form.openid.data, ask_for = ['nickname', 'email']) return render_template('login.html', title = 'Sign In', form = form, providers = app.config['OPENID_PROVIDERS'])
      
      







いくつかの新しいモジュールをインポートしており、そのうちのいくつかは後で使用されることに注意してください。









以前のバージョンとの違いはほとんどありません。 表示機能に新しいデコレーターを追加しました。 oid.loginhandler Flask-OpenID



おかげでoid.loginhandler Flask-OpenID



はこれが認証の機能であることを認識します。









g



は、リクエストの存続期間中にデータを保存および交換するために設計されたグローバルなFlaskオブジェクトです。 その中に、現在のユーザーに関するデータを保存します。 関数本体の上部で、 g.user



の値を確認します。 ユーザーが既にログインしている場合は、メインページにリダイレクトします。 この場合、再度認証を試みても意味がありません。









redirect



を呼び出すときに使用したurl_for



関数は、渡されたビュー関数の名前のURL



を取得する機能を提供しURL



。 もちろん、 redirect('/index')



使用できますが、このために特別に設計された関数のURL



の構築を委任する非常に良い理由がありURL











また、承認フォームから受信したデータを処理するコードを更新しました。 ここで2つのことを行います。 最初に、 remember_me



フィールドの値をFlask セッションに保存します(Flask-SQLAlchemy拡張機能によって提供されるセッションであるdb.session



と混同しないでください)。 前述のように、 flask.g



オブジェクトはリクエストの有効期間中のみデータを保存できます。 flask.session



はより複雑なリポジトリです。 また、セッションに格納されたデータは、 1つのクライアントからのすべての後続の要求中に利用可能になります 。 情報は、明示的に削除されるまで保存されます。 この動作は、Flaskがクライアントごとに個別のセッションを保存するために可能です。









oid.try_login



呼び出すと、Flask-OpenIDを使用して認証プロセスが開始されます。 この関数は、Webフォームから取得したopenid



と、OpenIDプロバイダーから受け取るフィールドのリストの2つの引数を取ります。 User



モデルにはnickname



email



属性があるため、このデータをリクエストします。









OpenIDを介した認証は非同期です。 プロバイダーから肯定的な応答を受け取った場合、Flask-OpenIDはoid.after_login



デコレーターを使用して宣言された関数を呼び出します。 それ以外の場合、ユーザーは認証ページに戻ります。









OpenIDプロバイダーからの応答の処理



これは、 after_login



関数(ファイルapp/views.py



の実装がどのように見えるかです:









 @oid.after_login def after_login(resp): if resp.email is None or resp.email == "": flash('Invalid login. Please try again.') return redirect(url_for('login')) user = User.query.filter_by(email = resp.email).first() if user is None: nickname = resp.nickname if nickname is None or nickname == "": nickname = resp.email.split('@')[0] user = User(nickname = nickname, email = resp.email, role = ROLE_USER) db.session.add(user) db.session.commit() remember_me = False if 'remember_me' in session: remember_me = session['remember_me'] session.pop('remember_me', None) login_user(user, remember = remember_me) return redirect(request.args.get('next') or url_for('index'))
      
      







after_login



関数に渡されるresp



引数には、OpenIDプロバイダーから受信したデータが含まれます。









まず、サーバーからの応答にユーザーの電子メールが含まれていることを確認する必要があります。含まれていない場合は、認証できません。 受信したメールがデータベースに含まれているかどうかを確認します。 何も見つからない場合は、データベースに新しいユーザーを追加します。 一部のOpenIDプロバイダーはnickname



提供しないことに注意する価値がありますが、私たちにとってこれは問題ではなく、メールからの名前を使用できます。









その後、Flaskセッションからremember_me



値を取得しようとします。これは、 login



ビュー関数で保存した値と同じです。









次に、Flask-Loginモジュールからlogin_user



関数を呼び出して、最終的にアプリケーションでユーザーを承認します。









最後に、 next



属性で渡されたアドレスにユーザーをリダイレクトします。リクエストにそのようなパラメーターがない場合は、メインページにリダイレクトします。 next



パラメーターの背後にある考え方は非常に単純です。 特定のページを許可されたユーザーのみが閲覧できるようにしたいとします。 Flask-Loginでは、これらのページはlogin_required



デコレータを使用して指定できます。 匿名ユーザーがそのようなページを開こうとすると、自動的に認証ページにリダイレクトされますが、Flask-Loginはnext



パラメーターで元のページのURL



保存しURL



。 承認が完了した後、ユーザーをこのアドレスに送信するだけです。









Flask-Loginが認証のためにユーザーを送信する場所を知るために、初期化中にこれについて通知する必要があります(ファイルapp/__init__.py











 lm = LoginManager() lm.init_app(app) lm.login_view = 'login'
      
      







G.userグローバルオブジェクト



login



ビュー関数では、現在のユーザーが既に承認されているかどうかを判断するために、 g.user



の状態を確認しました。 これを機能させるには、Flask before_request



イベントを使用します。 before_request



デコレータを使用して宣言されたすべての関数は、リクエストが受信されるたびに表示関数の呼び出しの直前に起動されます。 したがって、 g.user



値をここ(ファイルapp/views.py



)に
正確に設定することは非常に論理的app/views.py











 @app.before_request def before_request(): g.user = current_user
      
      







必要なのはそれだけです。 Flask-Loginはcurrent_user



変数へのアクセスを提供します。さらに使用しやすいように、 g



この値へのリンクをコピーするだけです。 これで、現在のユーザーはどこでも、テンプレート内でも利用可能になります。









ホームページ表示



前の章では、実際のユーザーと投稿がないため、 index



関数でスタブオブジェクトを使用しました。 これでユーザーができました。次はそれを使用します。









 @app.route('/') @app.route('/index') @login_required def index(): user = g.user posts = [ { 'author': { 'nickname': 'John' }, 'body': 'Beautiful day in Portland!' }, { 'author': { 'nickname': 'Susan' }, 'body': 'The Avengers movie was so cool!' } ] return render_template('index.html', title = 'Home', user = user, posts = posts)
      
      







この機能に加えた変更は2つだけです。 最初に、 login_required



デコレータが追加されました。 これからは、登録ユーザーのみがこのページを表示できるようになります。









次に、先ほど使用したスタブではなく、g.userオブジェクトをテンプレートに直接渡します。









アプリケーションを起動します。









http://localhost:5000



にアクセスすると、メインページの代わりにログインページが表示されます。 OpenIDを使用した承認は、プロバイダーが提供するURL



を使用して行われます。 住所を手動で入力しないようにするには、テキストボックスの下にあるリンクのいずれかを使用できます。









承認プロセス中に、プロバイダーのWebサイトにリダイレクトされます。そこで、システムに入り、一部の情報をアプリケーションに転送する許可を与える必要があります。 この場合、リクエストしたパラメーターのみが送信されます。 メールアドレスとニックネーム。 OpenIDプロバイダーは、パスワードを含む個人情報を報告しません。









その後、認証済みユーザーとしてメインページに移動します。









また、 remember_me



フラグを試すこともできremember_me



。 有効にすると、ブラウザを閉じて再度開いた後でもシステムに残ります。









ログアウト



ログインを実装しました。ログアウトする機能を追加します。 これは非常に簡単に行われます(ファイルapp/views.py











 @app.route('/logout') def logout(): logout_user() return redirect(url_for('index'))
      
      







さらに、適切なリンクをテンプレートに追加する必要があります。 ページの上部、他のナビゲーションリンク(ファイルapp/templates/base.html



)の
隣に配置します







 <html> <head> {% if title %} <title>{{title}} - microblog</title> {% else %} <title>microblog</title> {% endif %} </head> <body> <div>Microblog: <a href="{{ url_for('index') }}">Home</a> {% if g.user.is_authenticated() %} | <a href="{{ url_for('logout') }}">Logout</a> {% endif %} </div> <hr> {% with messages = get_flashed_messages() %} {% if messages %} <ul> {% for message in messages %} <li>{{ message }} </li> {% endfor %} </ul> {% endif %} {% endwith %} {% block content %}{% endblock %} </body> </html>
      
      







それがいかに簡単かを見てください! g.user



の内容を確認するだけで、現在のユーザーが許可されている場合は、終了するリンクを追加します。 そのような場合は、直接アドレスの代わりにurl_for



を使用することをおurl_for



します。









最後の言葉



これで、ユーザー認証のための完全なシステムができました。 次の章では、ユーザープロファイルページを作成し、アバターを使用する機能を追加します。









時間を節約するために、リンクを使用して、この記事からのすべての変更を含むアプリケーションコードをダウンロードできます。

microblog-0.5.zipをダウンロードします











じゃあね!









ミゲル








All Articles