pythondjangoformslazy-evaluation

How to make Django form choices lazy-evaluated?


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

Each choice is, e.g., ("Saloon", "Saloon (15 cars)"). 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 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!


Solution

  • 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 utility function!