如何修改ModelMultipleChoiceField的选择

Bri*_*ian 5 python django django-forms

假设我有一些人为的模型:

class Author(Model):
   name = CharField()

class Book(Model):
   title = CharField()
   author = ForeignKey(Author)
Run Code Online (Sandbox Code Playgroud)

让我们说我想使用ModelForm for Book:

   class BookForm(ModelForm):
      class Meta:
         model = Book
Run Code Online (Sandbox Code Playgroud)

到目前为止简单.但是我们还要说我的数据库中有很多作者,而且我不想拥有这么长的多选字段.所以,我想在BookForm的ModelMultipleChoiceField作者字段上限制查询集.让我们也说我想要的查询集直到__init__,因为它依赖于要传递的参数.

这似乎可以解决这个问题:

class BookForm(ModelForm):
   class Meta:
      model = Book

   def __init__(self, letter):
      # returns the queryset based on the letter
      choices = getChoices(letter)
      self.author.queryset = choices
Run Code Online (Sandbox Code Playgroud)

当然,如果这才有效,我就不会在这里.这让我产生了一个AttributeError.'BookForm'对象没有属性'author'.所以,我也试过这样的东西,我尝试覆盖ModelForm的默认字段,然后再设置它:

class BookForm(ModelForm):
   author = ModelMultipleChoiceField(queryset=Author.objects.all())

   class Meta:
      model = Book

   def __init__(self, letter):
      choices = getChoices(letter)
      self.author.queryset = choices
Run Code Online (Sandbox Code Playgroud)

这产生了相同的结果.

有人知道这是怎么做的吗?

Car*_*yer 8

表单对象没有其字段作为属性,您需要查看"fields"属性,这是一个字典:

self.fields['author'].queryset = choices
Run Code Online (Sandbox Code Playgroud)

如果你想完全理解这里发生了什么,你可能会对这个答案感兴趣- 它是关于模型的,但是Forms的工作方式类似.


Pao*_*ino 8

虽然卡尔对这些领域是正确的,但你也错过了超级级别的电话.我是这样做的:

class BookForm(ModelForm):
    author = ModelMultipleChoiceField(queryset=Author.objects.all())

    class Meta:
        model = Book

    def __init__(self, *args, **kwargs):
        letter = kwargs.pop('letter')
        super(BookForm, self).__init__(*args, **kwargs)
        choices = getChoices(letter)
        self.fields['author'].queryset = choices
Run Code Online (Sandbox Code Playgroud)