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/ を要求します。

Django フォーム

ソースを見ると次のような内容です。(本来は改行無しです。読みやすいように改行してあります)

<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 での表示は次のようになりました。

Django フォーム

ソースは次のようになります。

<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} )

この状態でブラウザからみると、次のようにフォームが表示されます。

Django フォーム

フォームとデータ

フォームには次のようにディクショナリとしてデータを渡すことで、 それぞれのフィールドに対応する箇所に値を埋めることが可能です。

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" に渡した値が確かにフォームに表示されています。

Django フォーム

次に、ポストされたデータを受け取ることを考えます。

データをポストできるように、テンプレートを変更してサブミットボタンと 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} )

こうすることで、ポストされたデータをそのままフォームに取り込むことができます。 いわゆるスティッキーなフォームとなります。

Django フォーム

尚、上記のフォームの定義では実は全ての項目が必須項目になります。 このため、どれか入力せずにデータをサブミットすると自動的に次のエラーメッセージが表示されます。

フォームにはデータのバリデーションなどの機能があります。それらについてはまた別のページで説明します。 ここでは簡単なフォームを作り、それがどのように動作するか確認しました。

その他、次のようにウィジェットを指定することで、入力フィールドを変更することもできます。

from django import forms

class KakikomiForm(forms.Form):
     name = forms.CharField()
     email = forms.EmailField()
     body = forms.CharField(widget=forms.Textarea) 

確かに Body の入力フィールドが変わりました。

Django フォーム

その他の入力フィールドについては、Django フォームのフィールド型をみてください。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Python 入門