Question

J'ai un Django my_forms.py comme ceci:

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

Chaque choix est par exemple ( "Saloon", "Saloon (15 voitures)"). Ainsi, les choix sont calculés par cette fonction.

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

Mon problème est les fonctions choix sont CHAISE chaque fois que j'importer simplement my_forms.py. Je pense que cela est dû à la façon dont Django déclare ses champs: dans la classe, mais pas dans une méthode de classe. Ce qui est bien, mais mes importations views.py my_forms.py de sorte que les choix se font des recherches sur chaque demande quelle que soit la vue utilisée.

Je pensais que peut-être mettre choix = bodystyle_choices sans support fonctionnerait, mais je reçois:

'function' object is not iterable

Il est évident que je peux utiliser la mise en cache et de mettre les « my_forms à l'importation » juste dans les fonctions de vue nécessaires, mais cela ne change pas le point principal: mes choix doivent être paresseux

Était-ce utile?

La solution

Vous pouvez utiliser la fonction "paresseux":)

from django.utils.functional import lazy

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

très belle fonction util!

Autres conseils

Essayez d'utiliser un ModelChoiceField lieu d'un simple ChoiceField. Je pense que vous serez en mesure de réaliser ce que vous voulez en tordant vos modèles un peu. Jetez un oeil à la docs plus.

Je voudrais aussi ajouter que ModelChoiceFields sont lazy par défaut:)

L'expansion de ce que dit Baishampayan Ghose, cela devrait probablement être considérée comme l'approche la plus directe:

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 sont ici: https://docs.djangoproject.com /en/1.8/ref/forms/fields/#modelchoicefield

Ceci a l'avantage que form.cleaned_data['bodystyle'] est une instance de Bodystyle au lieu d'une chaîne.

Vous pouvez simplement utiliser (car je pense que Django 1.8):

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

Notez la parenthèse manquante. Si vous avez besoin de passer des arguments, je viens de faire une version spéciale de la fonction avec eux hardcoded juste pour cette forme.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top