Подтвердить что ты не робот

Ленивый выбор в форме 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" только в требуемые функции просмотра, но это не меняет основной момент: мой выбор должен быть ленивым!

4b9b3361

Ответ 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 вместо строки.