Pergunta

Eu tenho um my_forms.py Django assim:

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

Cada escolha é por exemplo ( "Saloon", "Saloon (15 carros)"). Assim, as escolhas são computados por esta função.

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

O meu problema é as escolhas funções estão sendo executados cada vez que eu my_forms.py meramente importação. Eu acho que isso é devido à forma como Django declara seus campos: na classe, mas não em um método de classe. O que é bom, mas os meus importações views.py my_forms.py assim as pesquisas escolhas são feitas em cada solicitação, não importa qual modo de exibição é usado.

Eu pensei que as escolhas talvez colocando = bodystyle_choices sem suporte iria funcionar, mas eu recebo:

'function' object is not iterable

Obviamente, eu posso usar o cache e colocar os "my_forms importação" apenas nas funções de visualização necessários, mas isso não muda o ponto principal: as minhas escolhas precisam ser preguiçoso

Foi útil?

Solução

Você pode usar a função de "preguiçoso":)

from django.utils.functional import lazy

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

muito bom função util!

Outras dicas

Tente usar um ModelChoiceField em vez de um simples ChoiceField. Eu acho que você vai ser capaz de conseguir o que você quer por ajustes seus modelos um pouco. Dê uma olhada na docs para mais.

Eu também acrescentaria que ModelChoiceFields são lazy por padrão:)

Expandindo o que Baishampayan Ghose disse, isso provavelmente deve ser considerada a abordagem mais direta:

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

Isto tem a vantagem de que form.cleaned_data['bodystyle'] é um exemplo Bodystyle em vez de uma string.

Agora você pode apenas usar (desde que eu acho que Django 1.8):

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

Observe o parêntese ausente. Se você precisar passar argumentos, eu só fazer uma versão especial da função com eles codificado apenas para esse formulário.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top