ModelFormを使うとモデルのフォームを簡単に作成し保存する事ができますが、手動でモデルのフィールドを設定したいケースもあります。
今回はModelFormを使う時に、手動でモデルのフィールドを設定する方法を2つ紹介します。関数ベースビューとクラスベースビューのどちらの書き方も紹介します。
おすすめは「方法2 save(commit=False)を使う」の”クラスベースビュー”の実装方法です。
モデルとフォームの作成
以下の様なタグ名と更新者のデータを持つTagモデルを作成します。
from django.db import models
from django.contrib.auth.models import User
class Tag(models.Model):
name = models.CharField('タグ名', max_length=100)
updated_by = models.ForeignKey(User, on_delete=models.CASCADE)
このTagモデル用のフォームは次の様になります。(Tagモデルのインポート分は省略しています)
from django.forms import ModelForm
class TagForm(ModelForm):
class Meta:
model = Tag
fields = ['name']
タグ名はユーザーに入力してもらうため fields = [‘name’] としています。updated_byは手動で設定するためfieldsには含めません。
次から本題です。updated_byを手動で設定する方法を4つ紹介します。
方法1 最初にインスタンスを作成する
1つ目の方法は最初にインスタンスを作成する方法です。Tagモデルのインスタンス作成時に更新者を設定し、TagFormの引数に作成したインスタンスを渡します。
関数ベースビュー
関数ベースのビューに書く場合のコードは以下の様になります。このコードは公式サイトで紹介されている方法です。
tag = Tag(updated_by=request.user)
form = TagForm(request.POST, instance=tag)
form.save()
クラスベースビュー CreateViewを使う場合
django.views.generic.editのCreateViewクラスを継承している場合は、以下の様にpostメソッドをオーバーライドすれば設定できます。
def post(self, request, *args, **kwargs):
self.object = Tag(updated_by=self.request.user)
return super(BaseCreateView, self).post(request, *args, **kwargs)
方法2 save(commit=False)を使う
2つ目の方法はsave(commit=False)を使う方法です。commit=Falseを設定するとデータベースにまだ保存されていないオブジェクトを返します。
関数ベースビュー その1
関数ベースのビューに書く場合のコードは以下の様になります。このコードは公式サイトで紹介されている方法です。
form = TagForm(request.POST)
tag = form.save(commit=False)
tag.updated_by = request.user
tag.save()
関数ベースビュー その2 saveメソッドをオーバーライド
saveメソッドをオーバーライドしても実現できます。
状況にもよりますが、「関数ベースビュー その1」の様に関数ベースビュー内にフィールドを編集するより、saveメソッドをオーバーライドした方が保守しやすいと思います。この場合のコードは以下の様になります。
class TagForm(ModelForm):
class Meta:
model = Tag
fields = ['name']
def save(self, user):
obj = super.save(commit=False)
obj.updated_by = user
obj.save()
return obj
関数ベースのビューでTagForm使うコードは以下の様になります。「関数ベースビュー その1」よりシンプルになりました。
form = TagForm(request.POST)
tag = form.save(request.user)
クラスベースビュー
「関数ベースビュー その2 saveメソッドをオーバーライド」で紹介したTagFormをクラスベースビューで使う方法です。私はこの方法が一番気に入っています。
CreateViewやUpdateView継承しているクラスベースビューの場合はform_validメソッドをオーバーライドすれば良いです。
def form_valid(self, form):
self.object = form.save(self.request.user)
return HttpResponseRedirect(self.get_success_url())
まとめ
ModelFormを使う時に手動でモデルのフィールドを設定する方法を複数紹介しました。どの方法を取るかは人それぞれですが、自分にとって一番開発・保守しやすい方法は何かを考えて適切な方法を選びましょう。
コメントを残す