Формы Django: как динамично создать маркировки ModelChoiceField

Я хотел бы создать динамические маркировки для формы. 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)
12
задан George Stocker 8 February 2013 в 14:39
поделиться

3 ответа

Вы можете использовать ModelChoiceField , а затем изменить выбор в ProfileForm .__ init__ динамически, например (при условии, что это уже ModelChoiceField):

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

h.name в этом примере будет использоваться в качестве метки выбора!

9
ответ дан 2 December 2019 в 18:51
поделиться

Вы можете создать свой собственный класс поля формы и перезаписать метод, генерирующий метку:

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

используйте его в своей форме так же, как вы это делали с ModelChoiceField:

horoscope = MyChoiceField(queryset = .....)
7
ответ дан 2 December 2019 в 18:51
поделиться

На самом деле последний пример кода содержит ошибки, а должно быть:

# 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): ...'

3
ответ дан 2 December 2019 в 18:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: