Django#3(フォームの値を受け取る)
内容
- テンプレートにフォームを設置する。
- POSTリクエストを受け取る
- リクエストの変数と値の取り出し
- レスポンスを返す(正常)
下準備
下記の内容でhelloを設定している事。
URL.py
設定に変更なし。GETもPOSTも同じ設定で受け取れる。
テンプレートにフォームを記述する。
テンプレートファイルを下記の通りに修正する。
<html>
<body>
<form action="/hello" method="post">
{% csrf_token %}
<div>
<label for="name">名前</label>
<input type="text" id="name" name="name">
</div>
<div>
<label for="email">メールアドレス</label>
<input type="mail" id="email" name="email">
</div>
<div>
<label for="message">内容</label>
<textarea id="message" name="message">{{ message }}</textarea>
</div>
<input type="submit" value="送信する">
</form>
</body>
</html>
説明。
-
{% csrf_token %}
タグについて- POSTメソッドはCSRF対策としてトークンで照合を行っている。
- そのトークンを設定するのがこのタグ。formタグ内に書く。処理は自動的に行われる。
- これが無いと不正アクセスとしてエラーが発生する。
- formが複数ある場合は、各formにそれぞれ書く。
- その他のフォーム部分は普通のHTMLで書ける。
- DBと紐づけて半自動で生成することも可能。今回はやらない。
views.pyにPOSTリクエストを受け取る処理を追記する。
views.pyのHelloViewにpostメソッドを追記する。
class HelloView(View):
def get(self, request, *args, **kwargs):
context = {
'message': "Hello World! from View!!",
}
return render(request, 'hello.html', context)
def post(self, request, *args, **kwargs):
context = {
'message': "POST method OK!!",
}
return render(request, 'hello.html', context)
hello = HelloView.as_view()
説明
- getメソッド
- 特に変更なし。
- postメソッド
- まるっと追加。内容はgetとほぼ同一。区別できるようにメッセージだけ変更。
- 動作としては、HTTPリクエストのリクエストメソッドに応じて
ビュークラス内のgetメソッドかpostメソッドが実行される。- なので、全く別の処理にしてもOK、同一の動作ならまとめるのもOK。今回はべた書き。
- pushとかdeleteへの挙動は不明。ブラウザ自身がgetとしてリクエストしてしまうので。
動作確認
この時点で、http://IPアドレス:8000/hello
にアクセスすると下記のような画面が表示される。
ボタンをクリックすると下記のような画面が表示される。
テキストボックスのメッセージがこの画面のように表示されていたら、POST用の処理が正しく呼び出されている。
まだ、フォームに入力した文字は保持されない。その処理は以下。
HTTPリクエストからフォームの入力値を取り出す
次に、POSTリクエストからフォームの入力値を受け取る方法。
HTTPリクエストに付随する情報はビュークラスのget, postメソッドの2番目の引数に入ってくる。
具体的には下記のrequest
def post(self, request, *args, **kwargs):
このrequestの詳細は下記ドキュメントを参照。ここではとりあえずフォームの入力値だけ取り出す。
リクエストとレスポンスのオブジェクト | Django ドキュメント | Django
値の取得はrequest.POST['フォームのID']
でOK。
このうち、request.POSTがDjangoのQueryDictという型で、Pythonの辞書型の拡張になっている。
フォームの入力値は普通に辞書型のようにアクセスできる。
QueryDict型の詳細は下記を参照。
レスポンスを返す
フォームの入力値にアクセスする手段が分かったので、ビュー関数とテンプレートを修正して、
入力値をそのまま埋め込んで返す処理を書く。
まずビュー関数の修正。request.POSTの値をそのままname, email, messageの各変数に設定している。
def post(self, request, *args, **kwargs):
context = {
'name': request.POST['name'],
'email': request.POST['email'],
'message': request.POST['message'],
}
return render(request, 'hello.html', context)
次いでテンプレートの修正。差分のみ記載。valueを付け加えた。
7c7
< <input type="text" id="name" name="name" value="{{ name }}">
---
> <input type="text" id="name" name="name">
11c11
< <input type="mail" id="email" name="email" value="{{ email }}">
---
> <input type="mail" id="email" name="email">
動作確認。http://IPアドレス:8000/helloにアクセスして、フォームに何か入力して、
ボタンをクリックして、入力した文字がそのまま残っていたらOK
入力値のチェックやDBと連携して保存したりとかの処理はまた別途。