python - prefetch_related - django debug toolbar
Opciones perezosas en forma de Django (3)
Tengo un Django my_forms.py así:
class CarSearchForm(forms.Form):
# lots of fields like this
bodystyle = forms.ChoiceField(choices=bodystyle_choices())
Cada opción es, por ejemplo ("Saloon", "Saloon (15 autos)"). Entonces las elecciones son calculadas por esta función.
def bodystyle_choices():
return [(bodystyle.bodystyle_name, ''%s (%s cars)'' %
(bodystyle.bodystyle_name, bodystyle.car_set.count()))
for bodystyle in Bodystyle.objects.all()]
Mi problema es que las funciones de elección se ejecutan cada vez que me limito a importar my_forms.py. Creo que esto se debe a la forma en que Django declara sus campos: en la clase pero no en un método de clase. Lo cual está bien, pero mi views.py importa my_forms.py para que las búsquedas de opciones se realicen en cada solicitud, sin importar qué vista se use.
Pensé que quizás poner opciones = bodystyle_choices sin soporte funcionaría, pero obtengo:
''function'' object is not iterable
Obviamente, puedo usar el almacenamiento en caché y poner "import my_forms" solo en las funciones de vista requeridas, pero eso no cambia el punto principal: ¡mis elecciones deben ser flojas!
Intente utilizar un ModelChoiceField en lugar de un simple ChoiceField. Creo que podrá lograr lo que quiere ajustando un poco sus modelos. Eche un vistazo a los documentos para más.
También agregaría que los ModelChoiceFields son lazy
por defecto :)
Puedes usar la función "floja" :)
from django.utils.functional import lazy
class CarSearchForm(forms.Form):
# lots of fields like this
bodystyle = forms.ChoiceField(choices=lazy(bodystyle_choices, tuple)())
muy buena función util!
Al extenderse sobre lo que Baishampayan Ghose dijo, este debería ser probablemente el enfoque más directo:
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())
Los documentos están aquí: https://docs.djangoproject.com/en/1.8/ref/forms/fields/#modelchoicefield
Esto tiene la ventaja de que form.cleaned_data[''bodystyle'']
es una instancia de Bodystyle
lugar de una cadena.