Djangoのフォーム(forms.Form)の使い方【Python】
- 作成日: 2020-12-04
- 更新日: 2023-12-26
- カテゴリ: Django
Djangoのフォームの使い方
Django(ジャンゴ)はPythonのWebフレームワークですが、このDjangoにはフォームの制作を助けるためのモジュールがあります。
それがdjango.formsモジュールです。
このモジュールには多数の便利なフォームが置かれています。
今回はこのモジュール内のdjango.forms.Formについて解説します。
このフォームはDjangoのフォームでもっとも基礎的なフォームと言えます。
このフォームよりもモデルとの連携性を高めたフォーム、django.forms.ModelForm
もありますが、こちらについては↓の記事をご覧ください。
モデルを作る
今回は適当なアプリとしてmyapp
を作ってある前提で話します。
アプリについて特別な設定はしていません。
また、掲示板アプリの制作を想定しています。
myapp/models.py
に↓のようにモデルを作ります。
from django.db import models
class Post(models.Model):
name = models.CharField(max_length=64, help_text='投稿者名')
content = models.CharField(max_length=1024, help_text='投稿内容')
Post
モデルは掲示板への投稿内容を表すモデルです。
フィールドには投稿者名を表すname
と、投稿内容を表すcontent
を作っておきます。
モデルに対応するフォームを作る
ではdjango.forms.Form
を使って先ほどのモデルに対応するフォームを作ります。
フォームは慣例的にforms.py
というモジュールに作られるのが一般的です。
今回はmyapp/forms.py
にモジュールを作ります。
↓のようにフォームを作ります。
from django import forms
class PostForm(forms.Form):
name = forms.CharField(max_length=64, help_text='投稿者名')
content = forms.CharField(max_length=1024, help_text='投稿内容')
django.forms.Form
を利用するには↑のようにforms
をインポートしておきます。
そしてforms.Form
を継承したクラスPostForm
を作ります。
これはモデルPost
のフォームだからPostForm
という命名になっています。
フォームを作ったらフォームの中にフィールドを作ります。
モデルに対応するようにname
フィールドとcontent
フィールドを作ります。
ここの作りが「2度手間だなぁ」と感じる方はdjango.forms.ModelForm
の利用を検討してみてください。
↑のname
やcontent
などのフィールドは、フォームを作る際の部品としてHTMLが出力されます。
このときフィールド名は<input>
タグのname
属性の値になります。
また、フィールドの引数を指定することで<input>
タグの属性を変化させることが出来ます。
↑の例ではmax_length
という引数は<input>
タグのmaxlength
属性になります。
help_text
引数は<input>
タグとは別の<span>
タグとして出力されます。
フォームを使ってビューを作る
myapp/views.py
にビューを作ります。
今回はhome_view()
とcreate_view()
を作ります。
home_view()
はパス/
のGET
を処理するビューです。
create_view()
はパス/create/
のPOST
を処理します。
home_view()
ではフォームをユーザーに表示するところをやります。
home_view()
の内容ですが、↓のようにします。
from django.shortcuts import render
from django.http import HttpResponse # <- create_view()で使う
from .models import Post # <- create_view()で使う
from .forms import PostForm
def home_view(request):
context = {}
context['form'] = PostForm()
return render(request, 'myapp/home.html', context)
↑のようにビューのコンテキストにform
という変数を作り、先ほど作ったPostForm
をオブジェクトにして代入しておきます。
こうすることでテンプレートファイル内からform
という変数を参照し、フォームを利用することが出来るようになります。
render()
でテンプレートファイルmyapp/home.html
を描画します。これの実体はmyapp/templates/myapp/home.html
です。
テンプレートでフォームを描画する
myapp/home.html
は↓のようになっています。
<form action="/create/" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">投稿する</button>
</form>
このテンプレートではユーザーにフォームを表示します。
ユーザーはこのフォームに入力を行い、投稿ボタンを押して掲示板に投稿するという想定です。
意外に思われるかもしれませんが、↑のようにDjangoのフォームは<form>
タグ自体を描画しません。
ですので<form>
タグは自分で書く必要があります。
最初に<form>
タグを書きます。
<form action="/create/" method="POST">
action
にはフォームの送信先のパスを指定します。これは{% url ... %}
を使っても大丈夫です。今回は解説の簡便さのために直書きしています。
method
にはフォームが送信するリクエストのメソッドを指定します。このフォームが送信するリクエストはデータベースに変更を加えるリクエストなのでPOST
を指定します。
次にCSRFトークンを描画します。
{% csrf_token %}
↑のようにすることでCSRFトークンが記述された<input>
タグを出力できます。
CSRFトークンとはWebアプリケーションのセキュリティを高めるトークンです。
これはCSRF攻撃を防御します。
CSRF攻撃に対して無力なWebアプリケーションはネットに公開しては駄目です。
CSRFについては詳しくは↓の記事をご覧ください。
次にフォームのフィールドをHTMLとして出力します。
{{ form.as_p }}
↑のようにform
を参照するとHTMLを出力することが出来ます。
おしりについてるas_p
というのは、フォーム内のフィールドを<p>
タグで囲って出力するという意味になります。
↑の出力を見ると<input>
タグが<p>
タグで囲われて出力されているのがわかります。
最後に投稿ボタンを配置します。
<button type="submit">投稿する</button>
これでフォームの描画は完了です。
アプリの/
にアクセスすると↓のようなフォームが表示されます。
フォームからのリクエストを処理する
再びmyapp/views.py
に戻ります。
次はcreate_view()
を作ります。
このビューはパス/create/
に対応していて、先ほど作ったフォームからのリクエストを処理するビューです。
create_view()
は↓のように作っておきます。
from django.shortcuts import render
from django.http import HttpResponse
from .models import Post
from .forms import PostForm
...
def create_view(request):
form = PostForm(request.POST)
if not form.is_valid():
return HttpResponse('invalid', status=500)
name = form.cleaned_data['name']
content = form.cleaned_data['content']
post = Post.objects.create(name=name, content=content)
return HttpResponse(f'{post.id}')
まず↓の部分です。
form = PostForm(request.POST)
request.POST
にはPOST
されたデータ、つまりname
やcontent
などのデータが入っています。
fomrs.Form
はコンストラクタの引数にrequest.POST
を指定すると、そのrequest.POST
のデータでフィールドを初期化します。
つまりこの段階でform
変数内のフィールドにはデータがセットされているわけです。
次に↓の部分です。
if not form.is_valid():
return HttpResponse('invalid', status=500)
フォームにはデータをバリデーション(検証)する仕組みがあります。
バリデーションと言うのは、データが不正かどうかチェックする機能のことです。
ソフトウェア開発においては基本的に、第3者からの入力と言うのはいっさい信用してはいけないというのが共通認識になってます。
そのため↑のようis_valid()
メソッドを呼び出してバリデーションを行います。
is_valid()
はフォームにセットされているデータが不正であればFalse
を返し、不正でなければTrue
を返します。
不正の場合はHttpResponse
でユーザーの画面にinvalid
と表示させ、処理を中断します。
次に↓の部分です。
name = form.cleaned_data['name']
content = form.cleaned_data['content']
フォームでバリデーションされたデータはフォームのcleaned_data
という辞書に保存されます。
このcleaned_data
を参照することでユーザーの入力したデータ(バリデーション済み)にアクセスすることが可能です。
↑の場合、cleaned_data
からname
とcontent
のフィールドの値を変数に保存しています。
次に↓の部分です。
post = Post.objects.create(name=name, content=content)
↑ではフォームのフィールドの値を使ってPost
オブジェクトを作成しています。
そして最後に↓の部分でユーザーの画面に、作成したPost
オブジェクトのIDを表示します。
return HttpResponse(f'{post.id}')
このビューを作ってからフォームにデータを入力して送信ボタンを押すと、画面にPost
オブジェクトのIDが表示されるようになります。
おわりに
今回はdjango.forms.Form
を解説しました。
このフォームは柔軟な設定が可能なので、知っておくと使う機会があるかもしれません。
ほとんどの場合django.forms.ModelForm
で用は足りるとは思いますが。
🦝 < アディオス、カウボーイ