LoginSignup
27
33

More than 5 years have passed since last update.

DjangoでModelChoiceFieldのquerysetを動的に指定する

Last updated at Posted at 2014-12-03

はじめに

マスタ参照してるリストボックスについて、ログインユーザーの権限に応じて選択可能なアイテムを制御したい…というケースが発生。

↓のモデルとフォームをサンプルに、調べて試してみたやり方のメモ。

models.py
class Book(models.Model):
    name = models.charField('name',max_length=255)
forms.py
class SampleForm(forms.Form):
    book = forms.ModelChoiceField(label='book',queryset=Book.objects.all())

フォーム生成後にquerysetを上書きする

たぶん、一番シンプルな方法。

form = SampleForm()
form.fields['book'].queryset = Book.objects.filter(...)

フォームの__init__でquerysetを引数に受け取って上書きする

forms.py
class SampleForm(forms.Form):
    book = forms.ModelChoiceField(label='book',queryset=Book.objects.none())
    def __init__(self, queryset=None, *args, **kwargs):
        super(SampleForm,self).__init__(*args,**kwargs)
        if queryset :
            self.fields['book'].queryset = queryset
form = SampleForm(queryset=Book.objects.filter(...))

super.__init__をコールしないと、self.fieldsが生成されないので注意。

デフォルトのquerysetどうするかは、フォームの役割次第。

querysetそのものを受け取らず、フィルタの条件に使うデータだけ受け取っておいて、querysetの生成はフォーム側で行う…という実装でも可。

forms.py
class SampleForm(forms.Form):
    book = forms.ModelChoiceField(label='book',queryset=Book.objects.none())
    def __init__(self, permission=None, *args, **kwargs):
        super(SampleForm,self).__init__(*args,**kwargs)
        self.fields['book'].queryset = self.get_book_list(permission)

    def get_book_list(self, permission=None):
        if not permission :
            return Book.objects.none()

        if permission == AAA :
            query = Q(...)
        elif permission == BBB :
            query = Q(...)
        # 必要なだけ処理書く...

        return Book.objects.filter(query)

本質的にやってることは同じ。
要は、Form.__init__の処理が終わってから、Form.fields['field_name'].querysetを上書きすればいい。

余談

Form.fieldsをいじれば、他のフィールドのいろんな属性をフォーム生成後に変更することができる。
フィールドそのものを追加・削除することもできるかも?

27
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
33