今回のお題
今回は、djangoのformクラスについてまとめます。
今まではModelFormクラスばかり使っていたのですが、諸事情あってこちらも必要になりました。
両方とも使えるに越したことはないと思うので、良い機会だと思って勉強します。
目次
- formクラスとModelFormクラスの違い
- 実装例
- まとめ
formクラスとModelフォームクラスの違い
まず最初に、FormクラスとModelFormクラスの違いを説明しておきます。
- ModelFormクラス
- 対応するモデルを指定して定義する
- フィールドの仕様(バリデーションなど)は基本的に元にしたモデルから引き継ぐ形になり、一部は変更できない
- フォームとモデルが紐づいているので、フォームに入力された内容を元にモデルの情報を保存したり更新したりするのが比較的容易
- Formクラス
- ModelFormとは異なり、対応するモデルを指定するわけではない
- フォームとモデルが紐づいていないので、フォームの内容とモデルの相互変換にはやや手間がかかる
- フィールドの仕様(バリデーションなど)は基本的にモデルから独立しているので、自由に設定可能(ただしモデルから設定を流用して手間を省くことはできない)
総じて、手間がかかりにくが良くも悪くもモデルの情報に縛られるのがModelFormクラスであり、自由度と引き換えに手間が犠牲になっているのがFormモデルといえます。
ModelFormを用いた実装例については以下をどうぞ。
実装例
今回は実装例として以下のコードをModelFormクラスからFormクラスに書き換えていきたいと思います。
class Book(models.Model):
title = models.CharField(verbose_name="タイトル", max_length=30)
comment = models.TextField(verbose_name="コメント")
class BookForm(ModelForm):
class Meta:
model = Book
fields = "__all__"
# method=="GET"やバリデーションエラー時の挙動は省略しています
def create(request):
if request.method == "POST":
form = BookForm(request.POST)
if form.is_valid():
form.save()
return render(request, "home.html")
これをFormクラスを用いて書き換えます。
class BookForm(form.Form):
title = forms.CharField(label="タイトル", max_length=30)
comment = forms.TextField(label="コメント")
フィールドの定義はmodels.フィールド型
ではなくforms.フィールド型
の形式です。
また、一部のオプション名が異なります(verbose_name
→label
など)。
また、基本的にオプションはモデルとは別で定義し直しになることに注意してください。
def create(request):
form = BookForm(request.POST)
if form.is_valid():
title = forms.cleaned_data.get("title")
comment = forms.cleaned_data.get("comment")
book = Book()
book.title = title
book.comment = comment
book.save()
formクラスのインスタンスに対してsaveメソッドをかけることができないので、手間が増えていますね。
まとめ
以上がFormクラスを用いた実装例になります。
今回はフィールドがtitle
とcomment
のみでしたが、そこが増えると大変そうですね。
基本的にModelFormクラスではなくFormクラスを用いるべきなのは、
- モデルにはないフィールドを追加したいとき
- バリデーションをモデルに設定されているものから変更したい時
上記のいずれかになるのかなと思いました。