我想为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)
默认标签由“配置文件”定义中指定的 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>??? = ???
任何人都知道如何处理这个问题?非常感谢任何帮助。
我找到了一些东西,但我不知道这是否是最佳解决方案。我将一些内容添加到类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)
答案 0 :(得分:9)
您可以使用ModelChoiceField
,然后动态更改ProfileForm.__init__
中的选项,例如(假设它已经是ModelChoiceField):
horoscopes = Horoscope.objects.all()
self.fields['horoscope'].choices = [(h.pk, h.name) for h in horoscopes]
此示例中的 h.name
将用作选择的标签!
答案 1 :(得分:7)
您可以创建自己的表单字段类并覆盖生成标签的方法:
class MyChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
# return your own label here...
return smart_unicode(obj)
以与使用ModelChoiceField相同的形式使用它:
horoscope = MyChoiceField(queryset = .....)
答案 2 :(得分:3)
实际上,最后一个代码示例包含错误:
# 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
然后它有效。使用'lambda obj:...'或'def get_label(obj)没有区别:...'