prefetch_related debug python django forms lazy-evaluation

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.