Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy choices in Django form

Tags:

I have a Django my_forms.py like this:

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

Each choice is e.g. ("Saloon", "Saloon (15 cars)"). So the choices are computed by this function.

def bodystyle_choices():       return [(bodystyle.bodystyle_name, '%s (%s cars)' %             (bodystyle.bodystyle_name, bodystyle.car_set.count()))             for bodystyle in Bodystyle.objects.all()] 

My problem is the choices functions are getting executed every time I merely import my_forms.py. I think this is due to the way Django declares its fields: in the class but not in a class method. Which is fine but my views.py imports my_forms.py so the choices lookups are done on every request no matter which view is used.

I thought that maybe putting choices=bodystyle_choices with no bracket would work, but I get:

'function' object is not iterable

Obviously I can use caching and put the "import my_forms" just in the view functions required but that doesn't change the main point: my choices need to be lazy!

like image 642
Tom Viner Avatar asked Feb 20 '09 14:02

Tom Viner


People also ask

How do you exclude a specific field from a ModelForm?

Set the exclude attribute of the ModelForm 's inner Meta class to a list of fields to be excluded from the form.

How do you make a field not editable in Django?

The disabled boolean argument, when set to True , disables a form field using the disabled HTML attribute so that it won't be editable by users. Even if a user tampers with the field's value submitted to the server, it will be ignored in favor of the value from the form's initial data.


2 Answers

You can use the "lazy" function :)

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

very nice util function !

like image 98
Sidi Avatar answered Oct 08 '22 18:10

Sidi


Try using a ModelChoiceField instead of a simple ChoiceField. I think you will be able to achieve what you want by tweaking your models a bit. Take a look at the docs for more.

I would also add that ModelChoiceFields are lazy by default :)

like image 26
Baishampayan Ghose Avatar answered Oct 08 '22 19:10

Baishampayan Ghose