例えば、Django で下記のモデルを定義したとする。
from django.db import models from django.contrib.auth.models import User class Category(models.Model): user = models.ForeinKey(User) name = models.CharField(max_length=255) class Entry(models.Model): user = models.ForeinKey(User) title = models.CharField(max_length=255) content = models.TextField() category = models.ForeinKey(Category)
次に ModelForm を使って
from django import forms from models Entry class EntryForm(forms.ModelForm): class Meta: model = Entry exclude = ("user",)
というフォームを定義する。
で、このフォームをテンプレートで表示すると、category テーブルにある全てのデータを選択できてしまう。ログインユーザーが作成したカテゴリだけを選択させたいのに。ちょっと困った。
Django のソースコードを見ると、ModelForm は models.ForeinKey のフィールドを forms.ModelChoiceField を使って表示していた。この ModelChoiceField はコンストラクタで選択肢(クエリセット)を渡せるみたいだ。
ということは、ログインユーザーが作成したカテゴリだけを選択させたい場合、ユーザーで絞り込んだクエリセットを渡せばいい。
フォームを定義するときは、ログインユーザーで絞り込んだクエリセットを渡せないので、ビュー内でフォームを作成した後に ModelChoiceField を差し替えれば OK。
form = EntryForm() queryset = Category.objects.filter(user=request.user) form.fields["category"] = forms.ModelChoiceField(queryset, initial=form.fields["category"].initial)
あちらこらちのビューに同じコードを書き散らすのは行儀がよろしくないので、フォームを生成する関数を定義するべきだな。