DjangoのFormの値の取得方法: is_validとcleaned_data
- 作成日: 2021-08-22
- 更新日: 2023-12-26
- カテゴリ: Django
DjangoのFormの値の取得方法
DjangoではHTMLで書かれるフォームをFormオブジェクトに抽象化して扱うことが出来ます。
Formオブジェクトにした場合、フォームのデータのやり取りはこのFormオブジェクトを通して行われます。
この記事ではFormから、フォームに入力された値(情報)を取得する方法を詳しく解説します。
結論から言うとFormから値を取得するにはFormの属性cleaned_dataを参照します。
title = form.cleaned_data['title']
cleaned_data
の参照ではFormのis_valid
メソッドの知識も合わせて必要になりますので、この記事で解説します。
具体的には↓について見ていきます。
- Formのデータを取得するおおまかな流れ
- 前提とするプロジェクトとアプリ
- 前提とするForm
- 前提とする関連モジュール
- POSTデータをFormにセットする
- cleaned_dataでFormからデータを取得する
関連記事
Djangoのフォーム(forms.Form)の使い方【Python】
Djangoのformの今どきな作り方【Python, モデルフォーム】
DjangoのFormの初期値の設定方法: initial属性の使い方
参考
フォームを使う | Django ドキュメント | Django
フォームとフィールドの検証 | Django ドキュメント | Django
Formのデータを取得するおおまかな流れ
Formからデータを取得する大まかな流れについて解説します。
データの取得の流れはだいたい↓のようなものです。
- ビューでGETを処理する
- GETに応じたフォームを描画する
- ユーザーがフォームに入力しPOSTで送信する
- ビューでPOSTを処理する
- POSTのデータをフォームに渡してバリデーションをする
- バリデーション済みのデータをフォームから取得する
というのがFormのデータを取得する大まかな流れになります。
つまりFormに格納されるデータというのはPOSTのデータなんですね。
そしてそのPOSTのデータがフォームでバリデーションされて、そのバリデーションされたデータをcleaned_data
で取得すると言う感じになります。
今回の解説ではGETでフォームを描画する所から解説します。
前提とするプロジェクトとアプリ
前提として、解説用に作成しているDjangoのプロジェクトはmysite
という名前になります。
それからmyapp
というアプリを作成済みです。
前提とするForm
まず前提とするFormですが、今回は本をテーマにフォームを定義したいと思います。
本のタイトルと説明を格納するフォームBookForm
を作ります。
このBookForm
はmyapp/forms.py
に保存しておきます。
# myapp/forms.py
from django import forms
class BookForm(forms.Form):
title = forms.CharField(
label='本のタイトル',
max_length=100,
required=True,
help_text='必須',
)
description = forms.CharField(
label='本の説明文',
widget=forms.Textarea,
required=False,
help_text='*任意',
)
BookForm
はtitle
とdescription
の2つの属性を持つシンプルなフォームです。
前提とする関連モジュール
関連モジュールとしてまずmysite/urls.py
は↓のようになっています。
# mysite/urls.py
from django.contrib import admin
from django.urls import path
from myapp.views import home
urlpatterns = [
path('admin/', admin.site.urls),
path('', home, name='myapp_home'),
]
今回は手抜きでアプリではなくmysite
(プロジェクト)のほうのurls.py
にルート情報を書いています。
myapp.views
のhome
ビューはインデックス用のビューになります。
それからmyapp/views.py
は↓のように定義しています。
# myapp/views.py
from django.shortcuts import render
from django.http import HttpResponse
from myapp.forms import BookForm
def home(request):
# GETメソッドを処理する
if request.method == 'GET':
form = BookForm() # フォームを作成して
context = { 'form': form } # コンテキストに保存して
return render(request, 'myapp/home.html', context) # 描画
# POSTメソッドを処理する
elif request.method == 'POST':
form = BookForm(request.POST) # POSTデータをフォームに保存する
if not form.is_valid(): # バリデーションを行う
# データが不正だったらフォームを再描画する
context = { 'form': form }
return render(request, 'myapp/home.html', context)
# ↓がフォームから値を取得している所
title = form.cleaned_data['title']
description = form.cleaned_data['description']
# 値を元にレスポンスを生成する
return HttpResponse(f'{title}: {description}')
# 未対応のメソッド
else:
return HttpResponse('不正なメソッドです', status=500)
このmyapp/views.py
が今回の解説の本丸となるところです。
これについて後述で詳しく見ていきます。
それからテンプレートファイルmyapp/templates/myapp/home.html
は↓のようになっています。
{# myapp/templates/myapp/home.html #}
<h1>本の情報登録フォーム</h1>
<form action="{% url 'myapp_home' %}" method='POST'>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="登録" />
</form>
こちらのテンプレートファイルではフォームを描画しています。
フォームのアクションは先ほどのhome
ビューへのルートを指定します。
method
はPOST
です。
これまでのビューとテンプレートを描画すると↓のような画面になります。
POSTデータをFormにセットする
肝心のmyapp/views.py
について詳しく見ていきます。
まずhome
ビュー内ではメソッドを処理して分岐しています。
def home(request):
# GETメソッドを処理する
if request.method == 'GET':
...
# POSTメソッドを処理する
elif request.method == 'POST':
....
# 未対応のメソッド
else:
....
request.method
がGET
の場合とPOST
の場合とで処理を分岐しています。
POST
メソッド内の処理を見てみます。
# POSTメソッドを処理する
elif request.method == 'POST':
form = BookForm(request.POST) # POSTデータをフォームに保存する
if not form.is_valid(): # バリデーションを行う
# データが不正だったらフォームを再描画する
context = { 'form': form }
return render(request, 'myapp/home.html', context)
# ↓がフォームから値を取得している所
title = form.cleaned_data['title']
description = form.cleaned_data['description']
# 値を元にレスポンスを生成する
return HttpResponse(f'{title}: {description}')
POST
メソッドの場合、request.POST
に送信されたデータが格納されています。
request.POST
のPOST
は辞書に似たデータ構造です。
この辞書をBookForm
のコンストラクタ(初期化関数)に渡します。
form = BookForm(request.POST) # POSTデータをフォームに保存する
こうすることでrequest.POST
のデータを持ったフォームを作ることが可能です。
あとはこのフォームのis_valid()
メソッドを呼び出して、フォーム内のデータをバリデーションさせます。
is_valid()
がTrue
であればフォーム内のデータは正常で、False
であれば異常になります。
is_validは内部ではerrors属性を参照しています。
errors属性はプロパティで、このプロパティを参照したときにフォームのfull_clean()メソッドが実行されます。
full_clean()は各種フィールドやフォームのバリデーションを一括で行っています。
is_valid()
がFalse
の場合は適当にHttpResponse
を生成してユーザーに不正なデータであることを通知します。
if not form.is_valid(): # バリデーションを行う
# データが不正だったらフォームを再描画する
context = { 'form': form }
return render(request, 'myapp/home.html', context)
cleaned_dataでFormからデータを取得する
フォームのデータが正常であればフォームの属性cleaned_data
を参照してフォーム内に保存されているデータを取得します。
cleaned_data
は辞書のようなオブジェクトで、辞書のように扱うことが出来ます。
# ↓がフォームから値を取得している所
title = form.cleaned_data['title']
description = form.cleaned_data['description']
あとは適当にフォームの値を使ってレスポンスを生成します。
# 値を元にレスポンスを生成する
return HttpResponse(f'{title}: {description}')
今回はレスポンスの生成はHttpResponse
を使って手抜きしていますが、もちろんrender()
などを使ってもOKです。
おわりに
今回はDjangoのFormの値の取得方法を見てみました。
フォームを使えばバリデーションなども簡単に行えますし、値の取得も手軽に行えます。
Djangoのフォームに慣れてしまえば色々手っ取り早くコードを書くことも出来るので、至れり尽くせりと言う感じですね。
🦝 < 笑顔をフォームする
🐭 < いい笑顔だ