2010-06-02 31 views
12

Chciałbym utworzyć etykiety dynamiczne dla formularzy. ModeloChoiceField i zastanawiam się, jak to zrobić. Mam następujące klasy formularza:Formy Django: jak dynamicznie tworzyć etykiety 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) 

domyślne etykiety są zdefiniowane przez unicode funkcji określonej w definicji profilu. Etykiety przycisków radiowych tworzonych przez ModelChoiceField muszą być jednak tworzone dynamicznie.

Najpierw pomyślałem, że mogę po prostu przesłonić ModelChoiceField, jak opisano w dokumentacji Django. Ale to tworzy statyczne etykiety. Pozwala zdefiniować dowolną etykietę, ale po dokonaniu wyboru ten wybór jest stały.

Więc myślę, że trzeba dostosować dodać coś do Init jak:

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>??? = ??? 

Każdy mający żadnego pojęcia, jak radzić sobie z tym? Każda pomoc byłaby bardzo doceniana.


Znalazłem coś, ale nie wiem, czy to najlepsze rozwiązanie. Dodam coś do Init części klasy ProfileForm następująco:

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

Czy miałeś na myśli "domyślne etykiety są zdefiniowane w funkcji' unicode' określonej w definicji _Horoscope_ " ? –

Odpowiedz

9

Można użyć ModelChoiceField a następnie zmienić wyborów w ty ProfileForm.__init__ dynamicznie, na przykład (przy założeniu, że jest to już ModelChoiceField):

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

h.name w tym przykładzie będzie użyty jako etykieta do wyboru!

+0

Kiedy próbuję Twojego rozwiązania, otrzymuję komunikat o błędzie: "Wybierz prawidłowy wybór, który nie jest jednym z dostępnych wyborów". Obawiam się, że Twoje rozwiązanie nie działa. Zasadniczo model Profil zdefiniował horoskop z obcym kluczem, a instancja Profil oczekuje wystąpienia modelu horoskopu, a nie tylko liczby całkowitej h.pk. – Henri

+0

Tak, miałem na myśli "domyślne etykiety są zdefiniowane w funkcji Unicode określonej w definicji Horoscope" – Henri

+0

Niestety, pomyliłem coś tutaj, to prawdopodobnie działałoby z normalnym ChoiceField, ale zobacz moje inne rozwiązanie z podkategorią ModelChoiceField! –

7

Można stworzyć własną klasę pola formularza i zastąpić metodę, która generuje etykietę:

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

używać go w postaci samego jak ty z ModelChoiceField:

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

Tak i to też napisałem w pierwotnym pytaniu. Tworzy to alternatywne etykiety, ale etykiety STATIC. Zobacz moją uwagę, która brzmi "Najpierw myślałem, że mogę po prostu przesłonić ModelChoiceField, jak opisano w dokumentacji Django ..." – Henri

3

rzeczywistości ostatni przykład kodu zawiera błędy i powinien być:

# 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 

To działa . Nie ma żadnej różnicy w używaniu "lambda obj: ..." lub "def get_label (obj): ..."

Powiązane problemy