Вопрос

У меня есть 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 таким образом, поиск вариантов выполняется по каждому запросу независимо от того, какой вид используется.

Я подумал, что, возможно, размещение choices=bodystyle_choices без скобок сработало бы, но я получаю:

'function' object is not iterable

Очевидно, что я могу использовать кэширование и поместить "import my_forms" только в требуемые функции просмотра, но это не меняет сути:мой выбор должен быть ленивым!

Это было полезно?

Решение

Вы можете использовать "ленивую" функцию :)

from django.utils.functional import lazy

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

очень приятная полезная функция!

Другие советы

Попробуйте использовать ModelChoiceField вместо простого ChoiceField.Я думаю, вы сможете достичь того, чего хотите, немного изменив свои модели.Взгляните на Документы для большего.

Я бы также добавил, что ModelChoiceFields - это lazy по умолчанию :)

Развивая то, что сказал Байшампаян Гхосе, это, вероятно, следует считать наиболее прямым подходом:

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 1.8):

class CarSearchForm(forms.Form):  
    # lots of fields like this
    bodystyle = forms.ChoiceField(choices=bodystyle_choices)  

Обратите внимание на отсутствующую круглую скобку.Если вам нужно передать аргументы, я просто создаю специальную версию функции с их жестким кодом только для этой формы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top