FlaskアプリケーションでWebフォームを使用する方法
序章
テキストフィールドやテキスト領域などの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サーバーを作成するファイル:
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
、スペシャルを渡す __name__
変数。Flaskが舞台裏でいくつかのパスを設定するために必要です。 テンプレートのレンダリングについては、チュートリアルFlaskアプリケーションでテンプレートを使用する方法で説明されています。
次に、というグローバルPythonリストを作成します messages
、Python辞書が含まれています。 各辞書には2つのキーがあります。 title
メッセージのタイトル、および content
メッセージの内容。 これは、データ保存方法の簡略化された例です。 実際のシナリオでは、データを永続的に保存し、より効率的に操作できるデータベースを使用します。
Pythonリストを作成した後、 @app.route()
ビュー関数を作成するためのデコレータ index()
. その中で、あなたはに呼び出しを返します render_template()
関数。ルートがHTMLテンプレートを表示する必要があることをFlaskに示します。 このテンプレートに名前を付けます index.html
(後で作成します)そして、という変数を渡します messages
それに。 この変数は messages
以前に値として宣言したリストをリストし、HTMLテンプレートで使用できるようにします。 表示機能については、チュートリアルFlaskとPython3を使用して最初のWebアプリケーションを作成する方法で説明されています。
次に、 templates
あなたのフォルダ flask_app
Flaskがテンプレートを検索するディレクトリ。次に、というテンプレートファイルを開きます。 base.html
、コードの繰り返しを避けるために他のテンプレートが継承するコードが含まれます。
- mkdir templates
- nano templates/base.html
内に次のコードを追加します 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ボイラープレートが含まれています。 The title
各ページのタイトルを設定するためにブロックが置き換えられ、 content
ブロックは各ページのコンテンツに置き換えられます。 ナビゲーションバーには2つのリンクがあります。1つは、を使用するインデックスページ用です。 url_for()
リンクするヘルパー関数 index()
表示機能、およびアプリケーションに1つを含めることを選択した場合は、[バージョン情報]ページ用のもう1つ。
次に、というテンプレートを開きます index.html
. これは、で参照したテンプレートです。 app.py
ファイル:
- nano 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>
タイトルを兼ねる見出し。
行でJinjaforloopを使用します {% for message in messages %}
の各メッセージを確認するには messages
リスト。 あなたは <div>
メッセージのタイトルとコンテンツを含むタグ。 タイトルを表示します <h3>
見出しとコンテンツ <p>
鬼ごっこ。
あなたの中に flask_app
仮想環境がアクティブ化されているディレクトリ、アプリケーションについてFlaskに通知します(app.py
この場合)を使用して FLASK_APP
環境変数:
- export FLASK_APP=app
次に、 FLASK_ENV
環境変数から development
アプリケーションを開発モードで実行し、デバッガーにアクセスします。 Flaskデバッガーの詳細については、Flaskアプリケーションでエラーを処理する方法を参照してください。 これを行うには、次のコマンドを使用します(Windowsでは、 set
それ以外の export
):
- export FLASK_ENV=development
次に、アプリケーションを実行します。
- flask run
開発サーバーが実行されている状態で、ブラウザーを使用して次のURLにアクセスします。
http://127.0.0.1:5000/
にメッセージが表示されます messages
インデックスページに表示されるリスト:
Webアプリケーションをセットアップしてメッセージを表示したので、ユーザーが新しいメッセージをインデックスページに追加できるようにする方法が必要になります。 これは、次のステップで設定するWebフォームを介して行われます。
ステップ2—フォームの設定
このステップでは、ユーザーがWebフォームを介してメッセージのリストに新しいメッセージを追加できるようにするページをアプリケーションに作成します。
開発サーバーを実行したままにして、新しいターミナルウィンドウを開きます。
まず、 app.py
ファイル:
- nano app.py
次のルートをファイルの最後に追加します。
# ...
@app.route('/create/', methods=('GET', 'POST'))
def create():
return render_template('create.html')
ファイルを保存して閉じます。
これ /create
ルートには methods
タプルを持つパラメーター ('GET', 'POST')
両方を受け入れる GET
と POST
リクエスト。 GET
と POST
HTTPメソッドです。 デフォルトでは、 GET
サーバーにインデックスページやAboutページを要求するなど、データを取得するために使用される要求が受け入れられます。 POST
リクエストは、特定のルートにデータを送信するために使用されます。これにより、サーバー上のデータが変更されることがよくあります。
この例では、 create
を使用したページ GET
リクエスト。 [作成]ページには、入力フィールドと[送信]ボタンを備えたWebフォームがあります。 ユーザーがWebフォームに入力して[送信]ボタンをクリックすると、 POST
リクエストはに送信されます /create
ルート。 そこでリクエストを処理し、送信されたデータを検証して、ユーザーが空のフォームを送信していないことを確認し、それをに追加します。 messages
リスト。
The create()
ビュー関数は現在、1つのことだけを実行します:と呼ばれるテンプレートをレンダリングします create.html
通常のGETリクエストを受信したとき。 次に、このテンプレートを作成してから、処理する関数を編集します POST
次のステップでリクエストします。
と呼ばれる新しいテンプレートファイルを開きます create.html
:
- nano 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>
タグを付ける value
の {{ request.form['title'] }}
. これは、ユーザーが入力したデータを復元して、問題が発生したときに失われないようにするのに役立ちます。 たとえば、ユーザーが必要なものを入力するのを忘れた場合 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()関数。
これらのインポートをファイルの最初の行に追加します。
from flask import Flask, render_template, request, url_for, flash, redirect
# ...
The flash()
関数は、フラッシュされたメッセージをクライアントのブラウザセッションに保存します。これには、秘密鍵を設定する必要があります。 この秘密鍵はセッションを保護するために使用されます。これにより、Flaskは、新しいメッセージページからインデックスページへの移動など、あるリクエストから別のリクエストへの情報を記憶できます。 ユーザーはセッションに保存されている情報にアクセスできますが、秘密鍵を持っていない限り変更することはできません。そのため、誰にも秘密鍵へのアクセスを許可してはなりません。 詳細については、セッションのFlaskドキュメントを参照してください。
秘密鍵は長いランダムな文字列である必要があります。 を使用して秘密鍵を生成できます os
os.urandom()メソッドを使用するモジュール。暗号化に適したランダムバイトの文字列を返します。 それを使用してランダムな文字列を取得するには、新しいターミナルを開き、次のコマンドを使用してPythonインタラクティブシェルを開きます。
- python
Pythonインタラクティブシェルで、 os
標準ライブラリからモジュールを呼び出し、 os.urandom()
次のような方法:
- import os
- os.urandom(24).hex()
次のような文字列が表示されます。
Output
'df0331cefc6c2b9a5d0208a726a5d1c0fd37324feba25506'
取得した文字列を秘密鍵として使用できます。
秘密鍵を設定するには、 SECRET_KEY
を介したアプリケーションへの構成 app.config
物体。 次の直後に追加します app
定義する前の定義 messages
変数:
# ...
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.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
それに続くコードがリクエストが POST
比較によるリクエスト request.method == '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()
インデックスページにリンクする関数。
ファイルを保存して閉じます。
次に、に移動します /create
Webブラウザを使用してルーティングします。
http://127.0.0.1:5000/create
選択したタイトルといくつかのコンテンツをフォームに入力します。 フォームを送信すると、インデックスページに新しいメッセージが表示されます。
最後に、フラッシュされたメッセージを表示し、「新しいメッセージ」ページへのリンクをのナビゲーションバーに追加します。 base.html
この新しいページに簡単にアクセスできるテンプレート。 基本テンプレートファイルを開きます。
- nano templates/base.html
新しいファイルを追加してファイルを編集します <a>
内のナビゲーションバーのFlaskAppリンクの後にタグを付ける <nav>
鬼ごっこ。 次に、新しいを追加します for
真上でループする content
ナビゲーションバーの下に点滅するメッセージを表示するには、ブロックします。 これらのメッセージは特別に利用可能です get_flashed_messages()
Flaskが提供する機能。 次に、というクラス属性を追加します alert
各メッセージに、その中にいくつかのCSSプロパティを与えます <style>
鬼ごっこ:
<!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シリーズの他のチュートリアルをご覧ください。