フラスコメガチュートリアル、パート3:フォーム

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



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



目次
パート1:Hello World!

パート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でのデプロイ





短い繰り返し



前のパートでは、ホームページ用のシンプルなテンプレートを定義し、仮想オブジェクトをまだ持っていないもののプロトタイプとして使用しました。 たとえば、ユーザーまたはレコード。



この記事では、アプリケーションに存在するギャップの1つを埋めます。 フォームの使用を検討します。



フォームは、Webアプリケーションで最も基本的なブロックの1つです。 フォームを使用すると、ユーザーはブログのエントリを残したり、アプリケーションにログインしたりできます。



この部分に従うには、マイクロブログアプリケーションは、前の記事の最後に残したものと同じでなければなりません。 アプリケーションがインストールされ動作していることを確認してください。





構成



フォームの処理には、 WTForms



ラッパーであり、Flaskアプリケーションと完全に統合されるFlask-WTF



拡張機能を使用します。



多くのFlask拡張機能には設定が必要なため、必要に応じて変更のために簡単にアクセスできるように、マイクロブログルートフォルダー内に設定ファイルを作成します。 ここから始めます(config.pyファイル):

 CSRF_ENABLED = True SECRET_KEY = 'you-will-never-guess'
      
      







簡単です。これらは、 Flask-WTF



拡張機能に必要な2つの設定です。 CSRF_ENABLED



は、偽のクロスサイトリクエストの防止を有効にします。 ほとんどの場合、このオプションを有効にすると、アプリケーションがより安全になります。



SECRET_KEY



CSRF



有効な場合にのみ必要です。 フォーム検証で使用される暗号化トークンを作成するために使用されます。 アプリケーションを作成するときは、秘密鍵を入手するのが難しいことを確認してください。



これで設定ができましたので、Flaskにそれを読み取って使用するように指示する必要があります。 Flaskアプリケーションオブジェクトが作成された直後にこれを行うことができます。 (ファイルapp / __ init__.py):

 from flask import Flask app = Flask(__name__) app.config.from_object('config') from app import views
      
      







ログインフォーム



Flask-WTF



フォームはForm



クラスのサブクラスオブジェクトとして表されます。 フォームサブクラスは、フォームフィールドをクラスの変数として単純に定義します。



識別システムと一緒に使用されるログインフォームを作成します。 アプリケーションでサポートするログインメカニズムは、ユーザー名/パスワードの標準タイプではありません-OpenIDをログインとして使用します。 OpenIDの利点は、認証がOpenIDプロバイダーを介して渡されるため、パスワードを確認する必要がないことです。これにより、ユーザーのサイトがより安全になります。



OpenIDログインには、OpenIDという1行のみが必要です。 また、フォームに[Remember Me]チェックボックスをドロップして、ユーザーがブラウザーにCookieを設定できるようにします。これにより、ユーザーが戻ったときにユーザー名が記憶されます。



最初のフォーム(ファイルapp / forms.py)を作成します。

 from flask.ext.wtf import Form from wtforms import TextField, BooleanField from wtforms.validators import Required class LoginForm(Form): openid = TextField('openid', validators = [Required()]) remember_me = BooleanField('remember_me', default = False)
      
      







クラスはそれ自体を語っていると確信しています。 Form



クラスと、必要な2つのフィールドクラスTextField



BooleanField







インポートされたRequired



は、ユーザーが送信したデータを検証するためにフィールドにアタッチできるバリデーターです。 Required



バリデーターは、フィールドが空白で送信されなかったことを確認するだけです。 Flask-WTF



には多くのバリデーターがありますが、今後いくつかの新しいバリデーターを使用します。



フォームテンプレート



フォームを含むHTMLテンプレートも必要です。 LoginForm



なことに、作成したLoginForm



クラスはHTMLでフォームフィールドをレンダリングする方法を知っているため、レイアウトに集中するだけです。 ログインテンプレートは次のとおりです:(app / templates / login.html file):

 <!-- extend from base layout --> {% extends "base.html" %} {% block content %} <h1>Sign In</h1> <form action="" method="post" name="login"> {{form.hidden_tag()}} <p> Please enter your OpenID:<br> {{form.openid(size=80)}}<br> </p> <p>{{form.remember_me}} Remember Me</p> <p><input type="submit" value="Sign In"></p> </form> {% endblock %}
      
      







継承演算子を介してbase.html



テンプレートを再び使用し、それを拡張していることに注意してください。 すべてのテンプレートでこれを行い、レイアウトがすべてのページで一貫していることを確認します。



通常のHTMLフォームとテンプレートにはいくつかの興味深い違いがあります。 テンプレートは、 form



テンプレート引数で割り当てたばかりのフォームクラスのインスタンスを想定しています。 今後、このテンプレートを返すビュー関数を作成するときに、このテンプレート引数の送信を処理します。



テンプレートパラメータform.hidden_tag()



は、CSRFが設定ファイルに含まれないように非表示フィールドに置き換えられます。 CSRFが有効な場合、このフィールドはすべてのフォームにある必要があります。



フォームのフィールドはフォームオブジェクトによって指定されます。フィールドを挿入するテンプレートの場所で引数{{form.field_name}}



を参照するだけです。 一部のフィールドは引数を取る場合があります。 この場合、フォームに幅80文字のopenidフィールドを作成するように依頼します。



フォームクラスで送信ボタンを定義しなかったため、通常のフィールドとして定義する必要があります。 送信フィールドにはデータが含まれないため、フォームクラスで定義する必要はありません。



フォーム提出



フォームを見る前の最後のステップは、テンプレートをレンダリングするプレゼンテーション関数を書くことです。



フォームオブジェクトをテンプレートに渡すだけでよいため、これは実際には非常に簡単です。 新しいビュー関数(app / views.pyファイル)は次のとおりです。

 from flask import render_template, flash, redirect from app import app from forms import LoginForm #   index    @app.route('/login', methods = ['GET', 'POST']) def login(): form = LoginForm() return render_template('login.html', title = 'Sign In', form = form)
      
      







LoginForm



クラスをインポートし、そのインスタンスを作成して、テンプレートに送信しました。 フォームフィールドを描画するために必要なのはこれだけです。



flash



インポートとredirect



注意を払いません。 後でそれらを使用します。



別の革新は、 route



デコレータのメソッド引数です。 ここで、ビュー関数がGET



およびPOST



リクエストを受け入れることをFlaskに伝えます。 これがないと、送信はGET



要求のみを受け入れます。 ユーザーが入力したデータを含むフォームを送信するPOST



リクエストを受け取りたい。



この段階で、アプリケーションを起動し、ブラウザでフォームを確認できます。 開始後、ビュー関数loginに関連付けたアドレスを開きます: http:// localhost:5000 / login



データを受信する部分はプログラムしていないため、送信ボタンをクリックしても効果はありません。



フォームデータの取得

Flask-WTF



が作業を容易にするもう1つの分野は、送信されたデータの処理です。 これはlogin



ビュー関数の新しいバージョンで、フォームデータ(app / views.pyファイル)を検証して保存します。

 @app.route('/login', methods = ['GET', 'POST']) def login(): form = LoginForm() if form.validate_on_submit(): flash('Login requested for OpenID="' + form.openid.data + '", remember_me=' + str(form.remember_me.data)) return redirect('/index') return render_template('login.html', title = 'Sign In', form = form)
      
      







validate_on_submit



メソッドは処理全体を実行します。 フォームがユーザーに表示されたときに(つまり、ユーザーがデータを入力する前に)メソッドを呼び出した場合、ユーザーはFalse



を返します。この場合、テンプレートを描画する必要があることがわかります。



validate_on_submit



がフォーム送信リクエストの一部として一緒に呼び出された場合、すべてのデータを収集し、フィールドにアタッチされたバリデーターを実行します。すべて問題なければ、データの有効性を示すTrue



を返します。 これは、データをアプリケーションに含めるのに安全であることを意味します。



少なくとも1つのフィールドが検証に合格しない場合、関数はFalse



を返します。これにより、ユーザーの前にフォームが再び描画され、エラーを修正できるようになります。 後で、検証が失敗したときにエラーメッセージを表示する方法を学習します。



validate_on_submit



True



validate_on_submit



返すと、ビュー関数はFlaskからインポートされた2つの新しい関数を呼び出します。 Flash



機能は、ユーザーに表示される次のページにメッセージを表示する簡単な方法です。 この場合、ロギングに必要なインフラストラクチャができるまでデバッグにこれを使用し、代わりに、送信されたデータを示すメッセージを表示します。 flash



、ユーザーのフィードバックを提供する本番サーバーでも非常に役立ちます。



Flashメッセージはページに自動的に表示されません。テンプレートはサイトのレイアウトに合った形式でメッセージを表示する必要があります。 すべてのテンプレートがこの機能を継承するように、ベーステンプレートにメッセージを追加します。 これは更新された基本テンプレートです(ファイルapp / templates / base.html):

 <html> <head> {% if title %} <title>{{title}} - microblog</title> {% else %} <title>microblog</title> {% endif %} </head> <body> <div>Microblog: <a href="/index">Home</a></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>
      
      







メッセージの表示方法に説明が必要ないことを願っています。



ログインビューで使用した別の新しい機能はredirect



です。 この関数は、要求されたページではなく、クライアントのWebブラウザーを別のページにリダイレクトします。 プレゼンテーション機能では、前のパートで開発したメインページへのリダイレクトを使用しました。 関数がリダイレクトで終了した場合でも、フラッシュメッセージが表示されることに注意してください。



アプリケーションを実行し、フォームがどのように機能するかを確認するのに最適な時間です。 空のopenidフィールドを持つフォームを送信して、 Required



バリデーターが送信プロセスを停止する方法を確認してください。



フィールド検証の改善



現在の状態のアプリケーションでは、無効なデータで送信されたフォームは受け入れられません。 代わりに、フォームは再び修正のためにユーザーに送信されます。 これがまさに私たちに必要なものです。



私たちが見逃したのは、フォームの何が間違っていたかのユーザーからの通知でした。 幸いなことに、 Flask-WTF



はこのタスクを簡単にします。



フィールドの検証に失敗すると、 Flask-WTF



はフォームオブジェクトに視覚的なエラーメッセージを追加します。 これらのメッセージはテンプレートで利用できるため、表示するロジックを追加するだけです。



これは、フィールド検証メッセージを含むログインテンプレートです(ファイルapp / templates / login.html):

 <!-- extend base layout --> {% extends "base.html" %} {% block content %} <h1>Sign In</h1> <form action="" method="post" name="login"> {{form.hidden_tag()}} <p> Please enter your OpenID:<br> {{form.openid(size=80)}}<br> {% for error in form.errors.openid %} <span style="color: red;">[{{error}}]</span> {% endfor %}<br> </p> <p>{{form.remember_me}} Remember Me</p> <p><input type="submit" value="Sign In"></p> </form> {% endblock %}
      
      







私たちが行った唯一の変更は、openidフィールドの右側にバリデーターによって追加されたエラーメッセージを描画するループを追加することでした。 原則として、バリデーターが添付されたフィールドには、 form.errors._



としてエラーが追加されform.errors._



。 この場合、 form.errors.openid



を使用しform.errors.openid



。 これらのメッセージを赤で表示して、ユーザーの注意を喚起します。



OpenIDとの相互作用



実際、多くの人がすでにOpenIDをいくつか持っていることすら知らないという事実に直面します。 多くの主要なインターネットサービスプロバイダーがユーザーのOpenID認証をサポートしていることはあまり知られていません。 たとえば、Googleアカウントを持っている場合は、OpenIDを持っています。 Yahoo、AOL、Flickr、その他の多くのサービスと同様に。



頻繁に使用されるOpenIDのいずれかを使用してサイトへのユーザーアクセスを容易にするために、ユーザーがOpenIDを手動で入力する必要がないように、それらの一部にリンクを追加します。



紹介したいOpenIDプロバイダーのリストを定義することから始めましょう。 設定ファイル(config.pyファイル)でこれを行うことができます:

 OPENID_PROVIDERS = [ { 'name': 'Google', 'url': 'https://www.google.com/accounts/o8/id' }, { 'name': 'Yahoo', 'url': 'https://me.yahoo.com' }, { 'name': 'AOL', 'url': 'http://openid.aol.com/<username>' }, { 'name': 'Flickr', 'url': 'http://www.flickr.com/<username>' }, { 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]
      
      







ログインビュー関数でこのリストを使用する方法を見てみましょう。

 @app.route('/login', methods = ['GET', 'POST']) def login(): form = LoginForm() if form.validate_on_submit(): flash('Login requested for OpenID="' + form.openid.data + '", remember_me=' + str(form.remember_me.data)) return redirect('/index') return render_template('login.html', title = 'Sign In', form = form, providers = app.config['OPENID_PROVIDERS'])
      
      







ここでは、 app.config



キーで設定を検索して設定を取得します。 リストは、テンプレート引数としてrender_template



呼び出しに追加されます。



ご想像のとおり、これを終了するには別の手順を実行する必要があります。 次に、ログインテンプレート(ファイルapp / templates / login.html)でこれらのプロバイダーへのリンクを表示する方法を指定する必要があります。

 <!-- extend base layout --> {% extends "base.html" %} {% block content %} <script type="text/javascript"> function set_openid(openid, pr) { u = openid.search('<username>') if (u != -1) { // openid requires username user = prompt('Enter your ' + pr + ' username:') openid = openid.substr(0, u) + user } form = document.forms['login']; form.elements['openid'].value = openid } </script> <h1>Sign In</h1> <form action="" method="post" name="login"> {{form.hidden_tag()}} <p> Please enter your OpenID, or select one of the providers below:<br> {{form.openid(size=80)}} {% for error in form.errors.openid %} <span style="color: red;">[{{error}}]</span> {% endfor %}<br> |{% for pr in providers %} <a href="javascript:set_openid('{{pr.url}}', '{{pr.name}}');">{{pr.name}}</a> | {% endfor %} </p> <p>{{form.remember_me}} Remember Me</p> <p><input type="submit" value="Sign In"></p> </form> {% endblock %}
      
      







これらのすべての変更に関連して、テンプレートはやや長いことが判明しました。 一部のOpenIDにはユーザー名が含まれているため、ユーザー名を要求してからOpenIDを作成するJavaScriptマジックが必要です。 ユーザーがプロバイダーのOpenIDリンクをクリックし、(オプションで)ユーザー名を入力すると、このプロバイダーのOpenIDがテキストボックスに挿入されます。





Google OpenIDリンクをクリックした後のログインページのスクリーンショット



最後の言葉



ログインフォームは大幅に進歩しましたが、実際には、ユーザーがシステムに入るために何もしていません。 私たちがしたことは、ログインプロセスのGUIに関連することだけでした。 これは、実際のログインを行う前に、ユーザーを記録できるデータベースが必要だからです。



次の部分では、データベースを作成して起動します。少し後でログインシステムを完成させますので、以下の記事の更新にご注目ください。



現在の状態のマイクロブログアプリケーションは、ここからダウンロードできます。

microblog-0.3.zip



zipファイルには、フラスコ仮想環境が含まれていないことに注意してください。 アプリケーションを開始する前に、最初の部分の指示に従って自分で作成します。



ご質問やご意見がありましたら、下に自由に残してください。



ミゲル



All Articles