23

我有一个这样的 Django my_forms.py:

class CarSearchForm(forms.Form):  
    # lots of fields like this
    bodystyle = forms.ChoiceField(choices=bodystyle_choices())  

每个选择例如(“轿车”、“轿车(15 辆汽车)”)。所以选择是由这个函数计算的。

def bodystyle_choices():  
    return [(bodystyle.bodystyle_name, '%s (%s cars)' %  
          (bodystyle.bodystyle_name, bodystyle.car_set.count()))  
          for bodystyle in Bodystyle.objects.all()]

我的问题是每次我只导入 my_forms.py 时都会执行选择函数。我认为这是由于 Django 声明其字段的方式:在类中但不在类方法中。这很好,但是我的views.py 导入了my_forms.py,因此无论使用哪个视图,都会在每个请求上完成选择查找。

我认为也许将choices=bodystyle_choices 不带括号会起作用,但我得到:

'function' 对象不可迭代

显然我可以使用缓存并将“import my_forms”放在所需的视图函数中,但这并没有改变重点:我的选择需要是懒惰的!

4

4 回答 4

49

您可以使用“懒惰”功能:)

from django.utils.functional import lazy

class CarSearchForm(forms.Form):  
    # lots of fields like this
    bodystyle = forms.ChoiceField(choices=lazy(bodystyle_choices, tuple)())

非常好的实用功能!

于 2009-05-10T11:21:16.050 回答
18

尝试使用 ModelChoiceField 而不是简单的 ChoiceField。我认为你可以通过稍微调整你的模型来实现你想要的。查看文档了解更多信息。

我还要补充一点,ModelChoiceFieldslazy默认是 :)

于 2009-02-20T14:33:58.177 回答
2

您现在可以使用(因为我认为是 Django 1.8):

class CarSearchForm(forms.Form):  
    # lots of fields like this
    bodystyle = forms.ChoiceField(choices=bodystyle_choices)  

注意缺少的括号。如果您需要传递参数,我只需为该表单制作一个特殊版本的函数,并将它们硬编码。

于 2019-03-27T01:08:09.523 回答
1

扩展 Baishampayan Ghose 所说的话,这可能应该被认为是最直接的方法:

from django.forms import ModelChoiceField

class BodystyleChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return '%s (%s cars)' % (obj.bodystyle_name, obj.car_set.count()))

class CarSearchForm(forms.Form):  
    bodystyle = BodystyleChoiceField(queryset=Bodystyle.objects.all())

文档在这里:https ://docs.djangoproject.com/en/1.8/ref/forms/fields/#modelchoicefield

这样做的好处form.cleaned_data['bodystyle']Bodystyle实例而不是字符串。

于 2015-04-08T14:32:53.987 回答