Django forms: how to dynamically create ModelChoiceField labels

人走茶凉 提交于 2019-12-28 06:03:48

问题


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)

回答1:


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!




回答2:


You can make your own form field class and overwrite the method that generates the label:

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

use it in your form same as you did with the ModelChoiceField:

horoscope = MyChoiceField(queryset = .....)



回答3:


Actually the last code example contains errors an should be:

# 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

Then it works. There is no difference in using 'lambda obj:...' or 'def get_label(obj): ...'



来源:https://stackoverflow.com/questions/2958792/django-forms-how-to-dynamically-create-modelchoicefield-labels

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!