Я хотел бы создать динамические маркировки для формы. 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>??? = ???
Кто-либо имеющий какую-либо идею, как обработать это? Любая справка ценилась бы очень.
Я нашел что-то, но я не знаю, является ли это лучшее решение. Я добавляю что-то к init части класса ProfileForm следующим образом:
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)
Вы можете использовать ModelChoiceField
, а затем изменить выбор в ProfileForm .__ init__
динамически, например (при условии, что это уже ModelChoiceField):
horoscopes = Horoscope.objects.all()
self.fields['horoscope'].choices = [(h.pk, h.name) for h in horoscopes]
h.name
в этом примере будет использоваться в качестве метки выбора!
Вы можете создать свой собственный класс поля формы и перезаписать метод, генерирующий метку:
class MyChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
# return your own label here...
return smart_unicode(obj)
используйте его в своей форме так же, как вы это делали с ModelChoiceField:
horoscope = MyChoiceField(queryset = .....)
На самом деле последний пример кода содержит ошибки, а должно быть:
# 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): ...'