Django表单:如何动态创建ModelChoiceField标签

Hen*_*nri 12 django django-forms

我想为forms.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)
Run Code Online (Sandbox Code Playgroud)

默认标签由"配置文件"定义中指定的unicode函数定义.但是,需要动态创建ModelChoiceField创建的单选按钮的标签.

首先,我认为我可以简单地重写ModelChoiceField,如Django文档中所述.但这会创建静态标签.它允许您定义任何标签,但一旦做出选择,该选择是固定的.

所以我认为我需要适应添加一些东西到init:

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>??? = ???
Run Code Online (Sandbox Code Playgroud)

任何人都知道如何处理这个?任何帮助将非常感激.


我发现了一些东西,但我不知道它是否是最好的解决方案.我在类ProfileForm 的init部分添加了一些内容,如下所示:

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)
Run Code Online (Sandbox Code Playgroud)

Ber*_*ant 9

您可以使用a ModelChoiceField然后ProfileForm.__init__动态更改您的选择,例如(假设它已经是ModelChoiceField):

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

h.name 在这个例子中将被用作选择的标签!


Ber*_*ant 7

您可以创建自己的表单字段类并覆盖生成标签的方法:

class MyChoiceField(ModelChoiceField):
   def label_from_instance(self, obj):
        # return your own label here...
        return smart_unicode(obj)
Run Code Online (Sandbox Code Playgroud)

以与使用ModelChoiceField相同的形式使用它:

horoscope = MyChoiceField(queryset = .....)
Run Code Online (Sandbox Code Playgroud)