views:

881

answers:

3

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!

+9  A: 

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

Baishampayan Ghose
+2  A: 

Another solution is to move the bodystyle field to the class constructor:

class CarSearchForm(forms.Form):
  def __init__(self, *args, **kwargs):
    super(CarSearchForm, self).__init__(*args, **kwargs)
    self.fields['bodystyle'] = forms.ChoiceField(choices=bodystyle_choices())
Jonas
I think I will keep the class definition part, but have self.fields['bodystyle'].choices = bodystyle_choices() in the constructor.
Tom Viner
+5  A: 

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 !

Simo