Django forms: how to dynamically create ModelChoiceField labels
django, django-forms
Solution
You could use a `ModelChoiceField` and then change the choices in you `ProfileForm.__init__` dynamically, eg (assuming that it is already a ModelChoiceField):
horoscopes = Horoscope.objects.all()
self.fields['horoscope'].choices = [(h.pk, h.name) for h in horoscopes]
`h.name` in this example will be used as the label of the choice!
Problem
I would like to create dynamic labels for a forms.ModelChoiceField and I'm wondering how to do that. I have the following form class: ``` 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) ``` The default labels are defined by the unicode function specified in the Profile definition. However the labels for the radio buttons created by the ModelChoiceField need to be created dynamically. First I thought I could simply override ModelChoiceField as described in the Django documentation. But that creates static labels. It allows you to define any label but once the choice is made, that choice is fixed. So I think I need to adapt add something to init like: ``` 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>??? = ??? ``` Anyone having any idea how to handle this? Any help would be appreciated very much. I found something but I don't know if it's the best solution. I add something to the init part of class ProfileForm as follows: ``` 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) ```