2010-06-02 3 views
12

Я хотел бы создать динамические метки для форм.ModelChoiceField, и мне интересно, как это сделать. У меня есть следующий класс формы:Django 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) 

метка по умолчанию определяется юникода функции, указанной в определении профиля. Однако метки для переключателей, созданных 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 следующим образом:

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

Вы имели в виду «метки по умолчанию, определенные в функции' unicode', указанной в определении _Horoscope_ " ? –

ответ

9

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

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

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

+0

Когда я пробую ваше решение, я получаю сообщение об ошибке: «Выберите правильный выбор. Этот выбор не является одним из доступных вариантов». Боюсь, что ваше решение не работает. В основном профиль модели определил гороскоп иностранных ключей, и экземпляр профиля ожидает экземпляр модели Гороскоп, а не только целое число h.pk. – Henri

+0

Да, я имел в виду, что метки по умолчанию определены в функции юникода, указанной в определении «Гороскоп». – Henri

+0

Извините, что я что-то здесь что-то допустил, вероятно, он работал бы с обычным ChoiceField, но я вижу другое решение с подклассификацией ModelChoiceField! –

7

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

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

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

horoscope = MyChoiceField(queryset = .....) 
+0

Да, и это то, что я написал в моем первоначальном вопросе. Это создает альтернативные метки, но метки STATIC. См. Мое замечание, в котором говорится: «Сначала я подумал, что могу просто переопределить ModelChoiceField, как описано в документации Django ...» – Henri

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): ...»

Смежные вопросы