2010-06-02 23 views
12

Me gustaría crear etiquetas dinámicas para forms.ModelChoiceField y me pregunto cómo hacerlo. Tengo la siguiente clase de formulario:Formularios Django: cómo crear dinámicamente etiquetas ModelChoiceField

class ProfileForm(forms.ModelForm): 

    def __init__(self, data=None, ..., language_code='en', family_name_label='Family name', horoscope_label='Horoscope type', *args, **kwargs): 
     super(ProfileForm, self).__init__(data, *args, **kwargs) 

     self.fields['family_name'].label = family_name_label 
     . 
     . 
     self.fields['horoscope'].label = horoscope_label 
     self.fields['horoscope'].queryset = Horoscope.objects.all() 

    class Meta: 
     model = Profile 

    family_name = forms.CharField(widget=forms.TextInput(attrs={'size':'80', 'class': 'contact_form'})) 
    . 
    . 
    horoscope = forms.ModelChoiceField(queryset = Horoscope.objects.none(), widget=forms.RadioSelect(), empty_label=None) 

Las etiquetas por defecto están definidos por la funciónUnicode especificado en la definición del perfil. Sin embargo, las etiquetas de los botones de radio creados por ModelChoiceField deben crearse dinámicamente.

Primero pensé que podría simplemente anular ModelChoiceField como se describe en la documentación de Django. Pero eso crea etiquetas estáticas. Le permite definir cualquier etiqueta, pero una vez que se realiza la elección, esa opción es fija.

Así que creo que es necesario para adaptarse a añadir algo init como:

class ProfileForm(forms.ModelForm): 

    def __init__(self, data=None, ..., language_code='en', family_name_label='Family name', horoscope_label='Horoscope type', *args, **kwargs): 
     super(ProfileForm, self).__init__(data, *args, **kwargs) 

     self.fields['family_name'].label = family_name_label 
     . 
     . 
     self.fields['horoscope'].label = horoscope_label 
     self.fields['horoscope'].queryset = Horoscope.objects.all() 
     self.fields['horoscope'].<WHAT>??? = ??? 

Cualquier persona que tenga alguna idea de cómo manejar esto? Cualquier ayuda sería apreciada mucho.


Encontré algo pero no sé si es la mejor solución. Añado algo a la init parte de ProfileForm clase de la siguiente manera:

class ProfileForm((forms.ModelForm): 

    def __init__(self, data=None, ..., language_code='en', family_name_label='Family name', horoscope_label='Horoscope type', *args, **kwargs): 
    super(ProfileForm, self).__init__(data, *args, **kwargs) 

     # this function is added 
     def get_label(self, language_code): 
      """ 
      returns the label in the designated language, from a related object (table) 
      """ 
      return HoroscopeLanguage.objects.get(horoscope=obj, language__language_code=language_code).horoscope_type_language 

     self.fields['family_name'].label = family_name_label 
     . 
     . 
     self.fields['horoscope'].queryset = Horoscope.objects.all() 
     self.fields['horoscope'].label_from_instance = lambda obj: "%s: Euro %.2f" % (HoroscopeLanguage.objects.get(horoscope=obj, language__language_code=language_code).horoscope_type_language, obj.price) 
     . 
     . 
     """ 
     The next code also works, the lambda function without the get_label function 
     """ 
     self.fields['horoscope'].label_from_instance = lambda obj: "%s: Euro %.2f" % (obj.horoscope_type, obj.price) 
     . 
     . 
     """ 
     But this code doesn't work. Anyone? 
     """ 
     self.fields['horoscope'].label_from_instance = get_label(obj, language_code) 
+0

¿Quiso decir "las etiquetas predeterminadas están definidas en la función' unicode' especificada en la _Horoscope_ definition " ? –

Respuesta

9

Se puede usar un ModelChoiceField y luego cambiar las opciones en que ProfileForm.__init__ dinámicamente, por ejemplo (suponiendo que ya es un ModelChoiceField):

horoscopes = Horoscope.objects.all() 
self.fields['horoscope'].choices = [(h.pk, h.name) for h in horoscopes] 

h.name en este ejemplo se utilizará como la etiqueta de la elección!

+0

Cuando pruebo su solución recibo un error: "Seleccione una opción válida. Esa elección no es una de las opciones disponibles". Me temo que su solución no funciona. Básicamente, el modelo Perfil ha definido un horóscopo de clave externa y una instancia de Perfil espera una instancia del modelo Horóscopo, no solo un número entero h.pk. – Henri

+0

Sí quise decir "las etiquetas predeterminadas están definidas en la función Unicode especificada en la definición Horoscope" – Henri

+0

Lo siento, confundí algo aquí, probablemente funcionaría con un ChoiceField normal, pero veré mi otra solución con la subclasificación de ModelChoiceField. –

7

Usted puede hacer su propia clase de campo de formulario y sobrescribir el método que genera la etiqueta:

class MyChoiceField(ModelChoiceField): 
    def label_from_instance(self, obj): 
     # return your own label here... 
     return smart_unicode(obj) 

utilizarlo en su forma misma como lo hizo con la ModelChoiceField:

horoscope = MyChoiceField(queryset = .....) 
+0

Sí y eso también es lo que escribí en mi pregunta original. Esto crea etiquetas alternativas, pero etiquetas ESTÁTICAS. Vea mi observación que dice "Primero pensé que podría simplemente anular ModelChoiceField como se describe en la documentación de Django ..." – Henri

3

En realidad, el El último ejemplo de código contiene errores y debe ser:

# this function is added 
def get_label(obj): 
    return '%s: Euro %.2f' % (HoroscopeLanguage.objects.get(horoscope=obj, language__language_code=language_code).horoscope_type_language, obj.price) 
. 
. 
. 

self.fields['horoscope'].label_from_instance = get_labels 

Entonces funciona . No hay diferencia en el uso de 'lambda obj: ...' o 'def get_label (obj): ...'

Cuestiones relacionadas