Django フォームの基本
Django には HTML のフォーム操作用のライブラリが用意されています。フォームクラスとテンプレートを組み合わせることで、 動的な Web フォームを簡単に作成できます。
ここでは簡単な入力フォームを作ることを通して、基本的な Django フォームの動作をざっとみていきます。
まず、テスト用の Django App を作ります。ここでは次のコマンドで keijiban という名前のアプリケーションを作りました。
$ python manage.py startapp keijiban
settings.py にアプリケーションの登録も行いましょう。
サンプルとして "書込みフォーム" の意味で KakikomiForm という名前のフォームを定義します。 keijiban サブディレクトリ内に、forms.py という名前を作り次の内容を記述します。
from django import forms
class KakikomiForm(forms.Form):
name = forms.CharField()
email = forms.EmailField()
body = forms.CharField()
この名前はサンプル用なので何でもかまいませんが、変更したら次からのコードも適当に読み替えてください。フィールドは name, email, body の三つを定義しました。
これでフォームクラスの定義は完了です。
次にフォームクラス KakikomiForm を表示する View を作ります。views.py に次を記述します。
from django.shortcuts import render
from django.http import HttpResponse
from keijiban.forms import KakikomiForm
def kakikomi(request):
f = KakikomiForm()
return HttpResponse(f)
単純にフォームを生成して、それを文字列として返すだけでどうなるかみてみましょう。
そのために、ブラウザからアクセスできるように URL を構成します。 アプリケーション内に urls.py を作成し次の内容とします。
from django.conf.urls import url
from keijiban import views
urlpatterns = [
url('^$', views.kakikomi, name='kakikomi'),
]
プロジェクトルートの urls.py で URL のパターンとビューを設定します。
...
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url('keijiban/', include('keijiban.urls')),
url(r'^admin/', admin.site.urls),
]
以上でフォーム、ビュー、そして URL の定義が終わりました。これでどのように表示されるか確認します。 開発サーバーを起動して、ブラウザから http://127.0.0.1:8000/keijiban/ を要求します。
ソースを見ると次のような内容です。(本来は改行無しです。読みやすいように改行してあります)
<input type="text" name="name" required id="id_name" />
<input type="email" name="email" required id="id_email" />
<input type="text" name="body" required id="id_body" />
フォームクラスのフィールド毎に、input タグが作られ、それぞれの name と id がフィールド名を元に生成されています。
フォームクラスの as_table() 関数を使うと出力は次のように変わります。コードはこちら・・・
from django.shortcuts import render
from django.http import HttpResponse
from keijiban.forms import KakikomiForm
def kakikomi(request):
f = KakikomiForm()
return HttpResponse(f.as_table())
Chrome での表示は次のようになりました。
ソースは次のようになります。
<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" required id="id_name" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input type="email" name="email" required id="id_email" /></td></tr>
<tr><th><label for="id_body">Body:</label></th><td><input type="text" name="body" required id="id_body" /></td></tr>
table タグの中に記述されるべき内容が、ラベルつきで出力されていることがわかります。 他のフィールドも自由に追加できるように、table タグ自体は出力されていません。下でわかるように、テンプレートで指定します。
その他 as_ul() や as_p() などで、 li タグや p タグとして出力することも可能です。
テンプレートに組み込む
これだけではまだ使い勝手がよくありませんので、テンプレートに組み込んでどのように使うかみてみましょう。
テンプレートを kakikomiform.html として次を用意します。
テンプレートはアプリケーションディレクトリ内の templates ディレクトリ以下に、さらにアプリケーション名のディレクトリを作成してそこに保存します。
ここでは keijiban/templates/keijiban/kakikomiform.html となります。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<title>書き込みフォーム</title>
</head>
<body>
<h1>掲示板 - 書き込みフォーム</h1>
<form action="" method="post">
<table>{{form1.as_table}}</table>
</form>
</body>
</html>
View を次のように変更します。
from django.shortcuts import render
from keijiban.forms import KakikomiForm
def kakikomi(request):
f = KakikomiForm()
return render(request, 'keijiban/kakikomiform.html', {'form1': f} )
この状態でブラウザからみると、次のようにフォームが表示されます。
フォームとデータ
フォームには次のようにディクショナリとしてデータを渡すことで、 それぞれのフィールドに対応する箇所に値を埋めることが可能です。
from django.shortcuts import render
from keijiban.forms import KakikomiForm
def kakikomi(request):
f = KakikomiForm({
'name':'Ichiro',
'email':'foo@bar.com',
'body': 'Hello, Django Form!'})
return render(
request,
'keijiban/kakikomiform.html',
{'form1': f} )
フォーム "KakikomiForm" に渡した値が確かにフォームに表示されています。
次に、ポストされたデータを受け取ることを考えます。
データをポストできるように、テンプレートを変更してサブミットボタンと CSRF トークンを追加します。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<title>書き込みフォーム</title>
</head>
<body>
<h1>掲示板 - 書き込みフォーム</h1>
<form action="" method="post">
{% csrf_token %}
<table>
{{form1.as_table}}
<tr><td colspan='2'><input type="submit" value="Submit"></td></tr>
</table>
</form>
</body>
</html>
そして、データがポストされたとき (HTTP リクエストのメソッドが POST のとき)、POST データをそのままフォームに渡します。
from django.shortcuts import render
from keijiban.forms import KakikomiForm
def kakikomi(request):
if request.method == 'POST':
f = KakikomiForm(request.POST)
else:
f = KakikomiForm()
return render(
request,
'keijiban/kakikomiform.html',
{'form1': f} )
こうすることで、ポストされたデータをそのままフォームに取り込むことができます。 いわゆるスティッキーなフォームとなります。
尚、上記のフォームの定義では実は全ての項目が必須項目になります。 このため、どれか入力せずにデータをサブミットすると自動的に次のエラーメッセージが表示されます。
フォームにはデータのバリデーションなどの機能があります。それらについてはまた別のページで説明します。 ここでは簡単なフォームを作り、それがどのように動作するか確認しました。
その他、次のようにウィジェットを指定することで、入力フィールドを変更することもできます。
from django import forms
class KakikomiForm(forms.Form):
name = forms.CharField()
email = forms.EmailField()
body = forms.CharField(widget=forms.Textarea)
確かに Body の入力フィールドが変わりました。
その他の入力フィールドについては、Django フォームのフィールド型をみてください。