Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
29
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

@44d

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

はじめに

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

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

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をいじれば、他のフィールドのいろんな属性をフォーム生成後に変更することができる。
フィールドそのものを追加・削除することもできるかも?

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
29
Help us understand the problem. What are the problem?