python 如何修改 ModelMultipleChoiceField 的选择

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/738301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 20:46:15  来源:igfitidea点击:

How to Modify Choices of ModelMultipleChoiceField

pythondjangodjango-forms

提问by Brian

Let's say I have some contrived models:

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

class Author(Model):
   name = CharField()

class Book(Model):
   title = CharField()
   author = ForeignKey(Author)

And let's say I want to use a ModelForm for Book:

假设我想对 Book 使用 ModelForm:

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

Simple so far. But let's also say that I have a ton of Authors in my database, and I don't want to have such a long multiple choice field. So, I'd like is to restrict the queryset on the BookForm's ModelMultipleChoiceField author field. Let's also say that the queryset I want can't be chosen until __init__, because it relies on an argument to be passed.

简单到此为止。但是,假设我的数据库中有大量作者,我不希望有这么长的多项选择字段。所以,我想限制 BookForm 的 ModelMultipleChoiceField 作者字段上的查询集。假设我想要的查询集在 之前无法选择__init__,因为它依赖于要传递的参数。

This seems like it might do the trick:

这似乎可以解决问题:

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

Of course, if that just worked I wouldn't be here. That gets me an AttributeError. 'BookForm' object has no attribute 'author'. So, I also tried something like this, where I try to override the ModelForm's default field and then set it later:

当然,如果那行得通,我就不会在这里。这让我得到一个 AttributeError。“BookForm”对象没有“作者”属性。所以,我也尝试过这样的事情,我尝试覆盖 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

Which produces the same result.

产生相同的结果。

Anyone know how this is intended to be done?

有谁知道这是如何完成的?

回答by Carl Meyer

Form objects don't have their fields as attributes, you need to look in the "fields" attribute, which is a dictionary:

表单对象没有它们的字段作为属性,您需要查看“字段”属性,它是一个字典:

self.fields['author'].queryset = choices

If you want to fully understand what's going on here, you might be interested in this answer- it's about Models, but Forms work similarly.

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

回答by Paolo Bergantino

Although Carl is correct about the fields, you're also missing a super class call. This is how I do it:

尽管 Carl 关于这些字段是正确的,但您也错过了一个超类调用。这就是我的做法:

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