Django形式的懒惰选择

Tom*_*ner 21 python forms django lazy-evaluation

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

class CarSearchForm(forms.Form):  
    # lots of fields like this
    bodystyle = forms.ChoiceField(choices=bodystyle_choices())  
Run Code Online (Sandbox Code Playgroud)

每种选择都是例如("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()]
Run Code Online (Sandbox Code Playgroud)

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

我认为也许选择= bodystyle_choices没有括号会起作用,但我得到:

'function' object is not iterable

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

Sid*_*idi 47

你可以使用"懒惰"功能:)

from django.utils.functional import lazy

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

非常好的util函数!

  • 这似乎不起作用,至少对于Django 1.6,因为`ChoiceField._set_choices`做`self._choices = self.widget.choices = list(value)` (10认同)
  • 绝对是高级解决方案,它应该是imo可接受的答案。 (2认同)
  • / agree是到目前为止我所见过的最干净的解决方案,它使您可以跳过验证问题,这与ModelChoiceField有重要区别。 (2认同)
  • 这对我在Django 1.7上根本不起作用,有人可以检查它是否真的有效吗?首先,当我使用'tuple'作为'lazy'的第二个参数时,它引发有关返回值的错误类型的异常(“ Lazy object返回意外类型”)。其次,当我在此处使用“列表”时,该函数将被调用一次。然后就不再调用它了,我拥有与开始时相同的值列表。 (2认同)

Bai*_*ose 18

尝试使用ModelChoiceField而不是简单的ChoiceField.我认为通过稍微调整模型,你将能够达到你想要的效果.查看文档了解更多信息.

我还要补充说,ModelChoiceFields lazy默认是:)