Ленивый выбор в форме Django
У меня есть 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 объявляет свои поля: в классе, но не в методе класса. Что хорошо, но мой view.py импортирует my_forms.py, поэтому поиск по выборам выполняется для каждого запроса независимо от того, какой вид используется.
Я думал, что, возможно, выбор вариантов = bodystyle_choices без скобки будет работать, но я получаю:
'function' object is not iterable
Очевидно, что я могу использовать кеширование и помещать "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)())
очень хорошая функция использования!
Ответ 2
Попробуйте использовать ModelChoiceField вместо простого ChoiceField. Я думаю, вы сможете достичь того, чего хотите, немного изменив свои модели. Посмотрите docs для более подробной информации.
Я бы также добавил, что ModelChoiceFields lazy
по умолчанию:)
Ответ 3
Развернувшись на том, что сказал Байшампаян Гос, это, вероятно, следует рассматривать как самый прямой подход:
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
вместо строки.