著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
テキストフィールドやテキスト領域などのWebフォームを使用すると、ユーザーはデータをアプリケーションに送信して、アクションを実行したり、より広い領域のテキストをアプリケーションに送信したりできます。 たとえば、ソーシャルメディアアプリケーションでは、ユーザーがページに新しいコンテンツを追加できるボックスをユーザーに提供できます。 もう1つの例は、ログインページです。このページでは、ユーザーにユーザー名を入力するためのテキストフィールドと、パスワードを入力するためのパスワードフィールドを提供します。 サーバー(この場合はFlaskアプリケーション)は、ユーザーが送信したデータを使用して、データが有効な場合はサインインするか、Invalid credentials!
のようなメッセージで応答して、送信したデータがそうではないことをユーザーに通知します。正しい。
Flask は、Python言語でWebアプリケーションを作成するための便利なツールと機能を提供する軽量のPythonWebフレームワークです。 このチュートリアルでは、Webフォームの使用方法を示す小さなWebアプリケーションを作成します。 アプリケーションには、Pythonリストに保存されているメッセージを表示するためのページと、新しいメッセージを追加するためのページがあります。 また、メッセージの点滅を使用して、ユーザーが無効なデータを送信したときにエラーを通知します。
前提条件
- ローカルのPython3プログラミング環境については、 Python3シリーズのローカルプログラミング環境をインストールしてセットアップする方法のチュートリアルに従ってください。 このチュートリアルでは、プロジェクトディレクトリを
flask_app
と呼びます。 - ルート、ビュー関数、テンプレートなどの基本的なFlaskの概念の理解。 Flaskに慣れていない場合は、FlaskとPythonを使用して最初のWebアプリケーションを作成する方法およびFlaskアプリケーションでテンプレートを使用する方法を確認してください。
- 基本的なHTMLの概念の理解。 背景知識については、HTMLを使用してWebサイトを構築する方法チュートリアルシリーズを確認できます。
ステップ1—メッセージの表示
このステップでは、Pythonディクショナリのリストに格納されているメッセージを表示するためのインデックスページを備えたFlaskアプリケーションを作成します。
まず、編集のためにapp.py
という名前の新しいファイルを開きます。
nano app.py
app.py
ファイル内に次のコードを追加して、単一ルートのFlaskサーバーを作成します。
フラスコ_app/app.py
from flask import Flask, render_template app = Flask(__name__) messages = [{'title': 'Message One', 'content': 'Message One Content'}, {'title': 'Message Two', 'content': 'Message Two Content'} ] @app.route('/') def index(): return render_template('index.html', messages=messages)
ファイルを保存して閉じます。
このファイルでは、最初にFlask
クラスとrender_template()
関数をflask
パッケージからインポートします。 次に、Flask
クラスを使用して、app
という新しいアプリケーションインスタンスを作成し、Flaskのセットアップに必要な特別な__name__
変数を渡します。舞台裏のいくつかのパス。 テンプレートのレンダリングについては、チュートリアルFlaskアプリケーションでテンプレートを使用する方法で説明されています。
次に、messages
というグローバルPythonリストを作成します。このリストには、Pythonディクショナリが含まれています。 各辞書には2つのキーがあります。メッセージのタイトル用のtitle
と、メッセージの内容用のcontent
です。 これは、データ保存方法の簡略化された例です。 実際のシナリオでは、データを永続的に保存し、より効率的に操作できるデータベースを使用します。
Pythonリストを作成したら、@app.route()
デコレータを使用して、index()
というビュー関数を作成します。 その中で、render_template()
関数への呼び出しを返します。これは、ルートにHTMLテンプレートを表示する必要があることをFlaskに示します。 このテンプレートにindex.html
という名前を付け(後で作成します)、messages
という変数をテンプレートに渡します。 この変数は、以前に値として宣言したmessages
リストを保持し、HTMLテンプレートで使用できるようにします。 表示機能については、チュートリアルFlaskとPython3を使用して最初のWebアプリケーションを作成する方法で説明されています。
次に、Flaskがテンプレートを検索するflask_app
ディレクトリにtemplates
フォルダーを作成し、base.html
というテンプレートファイルを開きます。このファイルには、他のテンプレートが回避するために継承するコードが含まれています。コードの繰り返し:
mkdir templates nano templates/base.html
base.html
ファイル内に次のコードを追加して、ナビゲーションバーとコンテンツブロックを含むベーステンプレートを作成します。
フラスコ_app/templates / base.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %} {% endblock %} - FlaskApp</title> <style> .message { padding: 10px; margin: 5px; background-color: #f3f3f3 } nav a { color: #d64161; font-size: 3em; margin-left: 50px; text-decoration: none; } </style> </head> <body> <nav> <a href="{{ url_for('index') }}">FlaskApp</a> <a href="#">About</a> </nav> <hr> <div class="content"> {% block content %} {% endblock %} </div> </body> </html>
ファイルを保存して閉じます。
この基本テンプレートには、他のテンプレートで再利用する必要があるすべてのHTMLボイラープレートが含まれています。 title
ブロックは各ページのタイトルを設定するために置き換えられ、content
ブロックは各ページのコンテンツに置き換えられます。 ナビゲーションバーには2つのリンクがあります。1つはurl_for()
ヘルパー機能を使用してindex()
ビュー機能にリンクするインデックスページ用で、もう1つは[バージョン情報]ページ用です。アプリケーションで。
次に、index.html
というテンプレートを開きます。 これは、app.py
ファイルで参照したテンプレートです。
nano templates/index.html
次のコードを追加します。
フラスコ_app/templates / index.html
{% extends 'base.html' %} {% block content %} <h1>{% block title %} Messages {% endblock %}</h1> {% for message in messages %} <div class='message'> <h3>{{ message['title'] }}</h3> <p>{{ message['content'] }}</p> </div> {% endfor %} {% endblock %}
ファイルを保存して閉じます。
このコードでは、base.html
テンプレートを拡張し、content
ブロックの内容を置き換えます。 タイトルを兼ねる<h1>
の見出しを使用します。
{% for message in messages %}
行のJinjafor loop を使用して、messages
リストの各メッセージを調べます。 <div>
タグを使用して、メッセージのタイトルとコンテンツを含めます。 タイトルは<h3>
の見出しに表示し、コンテンツは<p>
タグに表示します。
仮想環境がアクティブになっているflask_app
ディレクトリで、FLASK_APP
環境変数を使用してアプリケーション(この場合はapp.py
)についてFlaskに通知します。
export FLASK_APP=app
次に、FLASK_ENV
環境変数をdevelopment
に設定して、アプリケーションを開発モードで実行し、デバッガーにアクセスします。 Flaskデバッガーの詳細については、Flaskアプリケーションでエラーを処理する方法を参照してください。 これを行うには、次のコマンドを使用します(Windowsでは、export
の代わりにset
を使用します)。
export FLASK_ENV=development
次に、アプリケーションを実行します。
flask run
開発サーバーが実行されている状態で、ブラウザーを使用して次のURLにアクセスします。
http://127.0.0.1:5000/
インデックスページに表示されるmessages
リストにメッセージが表示されます。
Webアプリケーションをセットアップしてメッセージを表示したので、ユーザーが新しいメッセージをインデックスページに追加できるようにする方法が必要になります。 これは、次のステップで設定するWebフォームを介して行われます。
ステップ2—フォームの設定
このステップでは、ユーザーがWebフォームを介してメッセージのリストに新しいメッセージを追加できるようにするページをアプリケーションに作成します。
開発サーバーを実行したままにして、新しいターミナルウィンドウを開きます。
まず、app.py
ファイルを開きます。
nano app.py
次のルートをファイルの最後に追加します。
フラスコ_app/app.py
# ... @app.route('/create/', methods=('GET', 'POST')) def create(): return render_template('create.html')
ファイルを保存して閉じます。
この/create
ルートには、GET
とPOST
の両方の要求を受け入れるためのタプル('GET', 'POST')
を持つmethods
パラメーターがあります。 GET
とPOST
はHTTPメソッドです。 デフォルトでは、GET
リクエストのみが受け入れられます。これらのリクエストは、サーバーにインデックスページやAboutページを要求するなどのデータの取得に使用されます。 POST
リクエストは、特定のルートにデータを送信するために使用されます。これにより、サーバー上のデータが変更されることがよくあります。
この例では、GET
リクエストを使用してcreate
ページをリクエストします。 [作成]ページには、入力フィールドと[送信]ボタンを備えたWebフォームがあります。 ユーザーがWebフォームに入力して[送信]ボタンをクリックすると、POST
リクエストが/create
ルートに送信されます。 そこでリクエストを処理し、送信されたデータを検証して、ユーザーが空のフォームを送信していないことを確認し、それをmessages
リストに追加します。
create()
ビュー関数は現在、1つのことだけを実行します。通常のGET要求を受信したときに、create.html
というテンプレートをレンダリングします。 次に、このテンプレートを作成し、次の手順でPOST
リクエストを処理するように関数を編集します。
create.html
という名前の新しいテンプレートファイルを開きます。
nano templates/create.html
次のコードを追加します。
フラスコ_app/templates / create.html
{% extends 'base.html' %} {% block content %} <h1>{% block title %} Add a New Message {% endblock %}</h1> <form method="post"> <label for="title">Title</label> <br> <input type="text" name="title" placeholder="Message title" value="{{ request.form['title'] }}"></input> <br> <label for="content">Message Content</label> <br> <textarea name="content" placeholder="Message content" rows="15" cols="60" >{{ request.form['content'] }}</textarea> <br> <button type="submit">Submit</button> </form> {% endblock %}
ファイルを保存して閉じます。
このコードでは、base.html
テンプレートを拡張し、content
ブロックをページのタイトルとして機能する<h1>
見出しに置き換えます。 <form>
タグで、method
属性をpost
に設定して、フォームデータがPOST
リクエストとしてサーバーに送信されるようにします。
フォームには、title
という名前のテキスト入力フィールドがあります。 これは、タイトルフォームデータにアクセスするためにアプリケーションで使用する名前です。 <input>
タグに{{ request.form['title'] }}
のvalue
を指定します。 これは、ユーザーが入力したデータを復元して、問題が発生したときに失われないようにするのに役立ちます。 たとえば、ユーザーが必要なcontent
テキスト領域に入力し忘れた場合、リクエストがサーバーに送信され、エラーメッセージが応答として返されますが、タイトルのデータは失われません。 request
グローバルオブジェクトに保存され、request.form['title']
からアクセスできます。
タイトル入力フィールドの後に、前述と同じ理由で、content
という名前のテキスト領域に値{{ request.form['content'] }}
を追加します。
最後に、フォームの最後に[送信]ボタンがあります。
これで、開発サーバーが実行されている状態で、ブラウザーを使用して/create
ルートに移動します。
http://127.0.0.1:5000/create
メッセージタイトルの入力フィールド、メッセージのコンテンツのテキスト領域、および[送信]ボタンを含む[新しいメッセージの追加]ページが表示されます。
このフォームは、POST
リクエストをcreate()
ビュー機能に送信します。 ただし、関数にはまだPOST
リクエストを処理するコードがないため、フォームに入力して送信しても何も起こりません。 次のステップでは、フォームが送信されたときに着信POST
リクエストを処理します。 送信されたデータが有効(空ではない)かどうかを確認し、メッセージのタイトルと内容をmessages
リストに追加します。
ステップ3—フォームリクエストの処理
このステップでは、アプリケーション側でフォームリクエストを処理します。 前の手順で作成したフォームを介してユーザーが送信したフォームデータにアクセスし、メッセージのリストに追加します。 また、メッセージ点滅を使用して、ユーザーが無効なデータを送信したときにユーザーに通知します。 フラッシュメッセージは1回だけ表示され、次のリクエストで消えます(たとえば、別のページに移動した場合)。
app.py
ファイルを開いて編集します。
nano app.py
まず、Flaskフレームワークから以下をインポートします。
- 前の手順で作成したHTMLフォームを介して送信される受信リクエストデータにアクセスするためのグローバルrequestオブジェクト。
- url_for()関数を使用してURLを生成します。
- flash()関数は、リクエストが処理されたときにメッセージをフラッシュします(すべてがうまくいったことをユーザーに通知するか、送信されたデータが有効でない場合は問題を通知します)。
- redirect()関数を使用して、クライアントを別の場所にリダイレクトします。
これらのインポートをファイルの最初の行に追加します。
フラスコ_app/app.py
from flask import Flask, render_template, request, url_for, flash, redirect # ...
flash()
機能は、フラッシュされたメッセージをクライアントのブラウザセッションに保存します。これには、秘密鍵を設定する必要があります。 この秘密鍵はセッションを保護するために使用されます。これにより、Flaskは、新しいメッセージページからインデックスページへの移動など、あるリクエストから別のリクエストへの情報を記憶できます。 ユーザーはセッションに保存されている情報にアクセスできますが、秘密鍵を持っていない限り変更することはできません。そのため、誰にも秘密鍵へのアクセスを許可してはなりません。 詳細については、セッションのFlaskドキュメントを参照してください。
秘密鍵は長いランダムな文字列である必要があります。 os
モジュールとos.urandom()メソッドを使用して秘密鍵を生成できます。このメソッドは、暗号化に適したランダムなバイトの文字列を返します。 それを使用してランダムな文字列を取得するには、新しいターミナルを開き、次のコマンドを使用してPythonインタラクティブシェルを開きます。
python
Pythonインタラクティブシェルで、標準ライブラリからos
モジュールをインポートし、次のようにos.urandom()
メソッドを呼び出します。
import os os.urandom(24).hex()
次のような文字列が表示されます。
Output 'df0331cefc6c2b9a5d0208a726a5d1c0fd37324feba25506'
取得した文字列を秘密鍵として使用できます。
秘密鍵を設定するには、app.config
オブジェクトを介してSECRET_KEY
構成をアプリケーションに追加します。 messages
変数を定義する前に、app
定義の直後に追加します。
フラスコ_app/app.py
# ... app = Flask(__name__) app.config['SECRET_KEY'] = 'your secret key' messages = [{'title': 'Message One', 'content': 'Message One Content'}, {'title': 'Message Two', 'content': 'Message Two Content'} ] # ...
次に、create()
ビュー関数を次のように変更します。
フラスコ_app/app.py
# ... @app.route('/create/', methods=('GET', 'POST')) def create(): if request.method == 'POST': title = request.form['title'] content = request.form['content'] if not title: flash('Title is required!') elif not content: flash('Content is required!') else: messages.append({'title': title, 'content': content}) return redirect(url_for('index')) return render_template('create.html')
if
ステートメントでは、比較request.method == 'POST'
を介して、要求がPOST
要求である場合にのみ次のコードが実行されるようにします。
次に、送信されたタイトルとコンテンツをrequest.form
オブジェクトから抽出します。これにより、リクエスト内のフォームデータにアクセスできます。 タイトルが指定されていない場合、条件if not title
が満たされます。 その場合、flash()
機能を使用して、タイトルが必要であることをユーザーに通知するメッセージを表示します。 これにより、メッセージがフラッシュメッセージリストに追加されます。 これらのメッセージは、後でbase.html
テンプレートの一部としてページに表示されます。 同様に、コンテンツが提供されない場合、条件elif not content
が満たされます。 その場合は、フラッシュされたメッセージのリストに'Content is required!'
メッセージを追加します。
メッセージのタイトルとコンテンツが適切に送信されている場合は、messages.append({'title': title, 'content': content})
の行を使用して、ユーザーが指定したタイトルとコンテンツを含む新しい辞書をmessages
リストに追加します。 次に、redirect()
関数を使用して、ユーザーをインデックスページにリダイレクトします。 url_for()
機能を使用して、インデックスページにリンクします。
ファイルを保存して閉じます。
次に、Webブラウザを使用して/create
ルートに移動します。
http://127.0.0.1:5000/create
選択したタイトルといくつかのコンテンツをフォームに入力します。 フォームを送信すると、インデックスページに新しいメッセージが表示されます。
最後に、フラッシュされたメッセージを表示し、[新しいメッセージ]ページへのリンクをbase.html
テンプレートのナビゲーションバーに追加して、この新しいページに簡単にアクセスできるようにします。 基本テンプレートファイルを開きます。
nano templates/base.html
<nav>
タグ内のナビゲーションバーのFlaskAppリンクの後に新しい<a>
タグを追加して、ファイルを編集します。 次に、content
ブロックのすぐ上に新しいfor
ループを追加して、ナビゲーションバーの下に点滅するメッセージを表示します。 これらのメッセージは、Flaskが提供する特別なget_flashed_messages()
機能で利用できます。 次に、alert
というクラス属性を各メッセージに追加し、<style>
タグ内にいくつかのCSSプロパティを指定します。
フラスコ_app/templates / base.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %} {% endblock %} - FlaskApp</title> <style> .message { padding: 10px; margin: 5px; background-color: #f3f3f3 } nav a { color: #d64161; font-size: 3em; margin-left: 50px; text-decoration: none; } .alert { padding: 20px; margin: 5px; color: #970020; background-color: #ffd5de; } </style> </head> <body> <nav> <a href="{{ url_for('index') }}">FlaskApp</a> <a href="{{ url_for('create') }}">Create</a> <a href="#">About</a> </nav> <hr> <div class="content"> {% for message in get_flashed_messages() %} <div class="alert">{{ message }}</div> {% endfor %} {% block content %} {% endblock %} </div> </body> </html>
ファイルを保存して閉じ、ブラウザにhttps://127.0.0.1:5000
をリロードします。 これで、ナビゲーションバーに/create
ルートにリンクする「作成」アイテムが表示されます。
フラッシュメッセージがどのように機能するかを確認するには、[作成]ページに移動し、2つのフィールドに入力せずに[送信]ボタンをクリックします。 次のようなメッセージが表示されます。
インデックスページに戻ると、ベーステンプレートの一部として表示されていても、ナビゲーションバーの下にある点滅したメッセージが消えることがわかります。 フラッシュされたメッセージでない場合は、ベーステンプレートからも継承されるため、インデックスページにも表示されます。
タイトルはあるが内容は含まれていないフォームを送信してみてください。 「コンテンツが必要です!」というメッセージが表示されます。 ナビゲーションバーのFlaskAppリンクをクリックしてインデックスページに戻り、[戻る]ボタンをクリックして[作成]ページに戻ります。 メッセージの内容がまだ残っていることがわかります。 これは、前のリクエストを保存するため、[戻る]ボタンをクリックした場合にのみ機能します。 ナビゲーションバーの[作成]リンクをクリックすると、新しいリクエストが送信され、フォームがクリアされます。その結果、点滅しているメッセージが消えます。
これで、ユーザー入力を受け取る方法、それを検証する方法、およびデータソースに追加する方法がわかりました。
注: messages
リストに追加したメッセージは、サーバーが停止すると消えます。Pythonリストはメモリにのみ保存されるため、メッセージを永続的に保存するには、 SQLiteのようなデータベース。 Python 3でsqlite3モジュールを使用する方法をチェックして、PythonでSQLiteを使用する方法を学習してください。
結論
ユーザーがインデックスページに表示されるメッセージのリストにメッセージを追加できるFlaskアプリケーションを作成しました。 Webフォームを作成し、ユーザーがフォームを介して送信したデータを処理して、メッセージリストに追加しました。 また、フラッシュメッセージを使用して、ユーザーが無効なデータを送信したときにユーザーに通知しました。
Flaskの詳細については、Flaskシリーズの他のチュートリアルをご覧ください。