Формы Django: как динамически создавать метки ModelChoiceField - PullRequest
12 голосов
/ 02 июня 2010

Я хотел бы создать динамические метки для форм. 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)

Ответы [ 3 ]

9 голосов
/ 02 июня 2010

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

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

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

7 голосов
/ 02 июня 2010

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

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

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

horoscope = MyChoiceField(queryset = .....)
3 голосов
/ 04 июня 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...