我有一个像这样的Django my_forms.py:
class CarSearchForm(forms.Form):
# lots of fields like this
bodystyle = forms.ChoiceField(choices=bodystyle_choices())
每个选择都是例如(“Saloon”,“Saloon(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,因此无论使用哪个视图,都会对每个请求进行选择查找。
我认为可能选择= bodystyle_choices没有括号会起作用,但我得到:
'function' object is not iterable
显然我可以使用缓存并将“import my_forms”放在所需的视图函数中,但这不会改变主要观点:我的选择需要是懒惰的!
答案 0 :(得分:47)
您可以使用“懒惰”功能:)
from django.utils.functional import lazy
class CarSearchForm(forms.Form):
# lots of fields like this
bodystyle = forms.ChoiceField(choices=lazy(bodystyle_choices, tuple)())
非常好的util函数!
答案 1 :(得分:18)
尝试使用ModelChoiceField而不是简单的ChoiceField。我认为通过稍微调整模型,你将能够达到你想要的效果。请查看docs了解更多信息。
我还要补充说默认情况下ModelChoiceFields为lazy
:)
答案 2 :(得分: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
实例而不是字符串。
答案 3 :(得分:0)
您现在可以使用(因为我认为是Django 1.8):
class CarSearchForm(forms.Form):
# lots of fields like this
bodystyle = forms.ChoiceField(choices=bodystyle_choices)
请注意缺少括号。如果您需要传递参数,则只需为函数创建一个特殊版本,并针对该表单对其进行硬编码。