2009-02-20 11 views
19

ho un my_forms.py Django come questo:scelte pigri in forma Django

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

Ogni scelta è per esempio ("Saloon", "Saloon (15 auto)"). Quindi le scelte sono calcolate da questa funzione.

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

Il mio problema è le scelte funzioni sono sempre eseguiti ogni volta che semplicemente importare my_forms.py. Penso che questo sia dovuto al modo in cui Django dichiara i suoi campi: nella classe ma non in un metodo di classe. Che va bene, ma il mio views.py importa my_forms.py in modo che le ricerche delle scelte vengano fatte su ogni richiesta indipendentemente dalla vista utilizzata.

ho pensato che forse mettendo le scelte = bodystyle_choices senza staffa avrebbe funzionato, ma ottengo:

'function' object is not iterable

Ovviamente posso usare la cache e mettere il "my_forms importazione" solo nelle funzioni di visualizzazione desiderata, ma che non lo fa cambia il punto principale: le mie scelte devono essere pigre!

risposta

43

È possibile utilizzare la funzione di "pigro" :)

from django.utils.functional import lazy 

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

molto bella funzione util!

+1

Definitivamente la soluzione superiore, questa dovrebbe essere la risposta accettata imo. –

+1

/agree è la soluzione più pulita che ho visto finora e questo consente di saltare i problemi con le convalide, una differenza importante rispetto a ModelChoiceField. – Hassek

+7

Questo non sembra funzionare, almeno con Django 1.6, perché 'ChoiceField._set_choices' fa' self._choices = self.widget.choices = list (valore) ' – spookylukey

18

Provare ad utilizzare ModelChoiceField invece di un semplice ChoiceField. Penso che sarai in grado di ottenere ciò che desideri modellando un po 'le tue modelle. Dai uno sguardo allo docs per ulteriori informazioni.

Vorrei anche aggiungere che ModelChoiceFields sono lazy di default :)

0

espansione su quello che ha detto Baishampayan Ghose, questo dovrebbe probabilmente essere considerato l'approccio più diretto:

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

Docs sono qui: https://docs.djangoproject.com/en/1.8/ref/forms/fields/#modelchoicefield

Questo ha il vantaggio che form.cleaned_data['bodystyle'] è un'istanza Bodystyle invece di un stringa.

Problemi correlati