Django 形式的懒惰选择
Posted
技术标签:
【中文标题】Django 形式的懒惰选择【英文标题】:Lazy choices in Django form 【发布时间】:2010-10-08 20:30:57 【问题描述】:我有一个这样的 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,因此无论使用哪个视图,都会在每个请求上完成选择查找。
我认为也许不带括号的选择=bodystyle_choices 会起作用,但我明白了:
'function' 对象不可迭代
显然我可以使用缓存并将“import my_forms”放在所需的视图函数中,但这并没有改变重点:我的选择需要是懒惰的!
【问题讨论】:
【参考方案1】:你可以使用“懒惰”功能:)
from django.utils.functional import lazy
class CarSearchForm(forms.Form):
# lots of fields like this
bodystyle = forms.ChoiceField(choices=lazy(bodystyle_choices, tuple)())
非常好的实用功能!
【讨论】:
绝对是最好的解决方案,这应该是 imo 接受的答案。 /agree 是迄今为止我见过的最干净的解决方案,这可以让您跳过验证问题,这是与 ModelChoiceField 的一个重要区别。 这似乎不起作用,至少在 Django 1.6 中是这样,因为ChoiceField._set_choices
可以做到 self._choices = self.widget.choices = list(value)
这对我在 Django 1.7 上根本不起作用,有人可以检查它是否真的有效吗?首先,当我使用 'tuple' 作为 'lazy' 的第二个参数时,它会引发关于错误类型的返回值(“惰性对象返回意外类型”)的异常。其次,当我在那里使用“列表”时,该函数被调用......一次!然后它不再被调用,并且我的值列表与开始时相同。【参考方案2】:
尝试使用 ModelChoiceField 而不是简单的 ChoiceField。我认为你可以通过稍微调整你的模型来实现你想要的。查看docs 了解更多信息。
我还要补充一点,ModelChoiceFields 默认为 lazy
:)
【讨论】:
【参考方案3】:您现在可以使用(因为我认为是 Django 1.8):
class CarSearchForm(forms.Form):
# lots of fields like this
bodystyle = forms.ChoiceField(choices=bodystyle_choices)
注意缺少的括号。如果您需要传递参数,我只需为该表单制作一个特殊版本的函数,并将它们硬编码。
【讨论】:
这应该是现代 Django 的答案。【参考方案4】:扩展Baishampyan 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
实例而不是字符串。
【讨论】:
以上是关于Django 形式的懒惰选择的主要内容,如果未能解决你的问题,请参考以下文章
Django - 当用户选择地图上的点时,如何以模式形式包含地图并将坐标保存到数据库?