2010-06-02 16 views
12

Vorrei creare etichette dinamiche per un modulo.ModelChoiceField e mi chiedo come farlo. Ho la seguente classe form:Forme di Django: come creare dinamicamente le etichette 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) 

le etichette predefinite sono definiti dalla funzione diunicode specificato nella definizione del profilo. Tuttavia, è necessario creare dinamicamente le etichette per i pulsanti di opzione creati da ModelChoiceField.

In primo luogo ho pensato che potevo semplicemente sostituire ModelChoiceField come descritto nella documentazione di Django. Ma questo crea etichette statiche. Ti permette di definire qualsiasi etichetta ma una volta effettuata la scelta, quella scelta è fissa.

Quindi penso che ho bisogno di adattarsi aggiungere qualcosa alla init come:

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

Chiunque avere alcuna idea di come gestire questa situazione? Qualsiasi aiuto sarebbe apprezzato molto.


Ho trovato qualcosa ma non so se è la soluzione migliore. Aggiungo qualcosa alla init parte della classe ProfileForm come segue:

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

Intendevi "le etichette predefinite sono definite nella funzione" unicode "specificata nella definizione" Hoshoscope " ? –

risposta

9

si potrebbe usare un ModelChoiceField e quindi modificare le scelte in voi ProfileForm.__init__ in modo dinamico, ad esempio (supponendo che è già un ModelChoiceField):

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

h.name in questo esempio verrà utilizzato come etichetta della scelta!

+0

Quando provo la tua soluzione ricevo un errore: "Seleziona una scelta valida. Quella scelta non è una delle scelte disponibili". Ho paura che la tua soluzione non funzioni. Fondamentalmente il profilo del modello ha definito un oroscopo a chiave esterna e un'istanza di profilo si aspetta un'istanza del modello di oroscopo, non solo un intero h.pk. – Henri

+0

Sì, intendevo "le etichette predefinite sono definite nella funzione Unicode specificata nella definizione Oroscopo" – Henri

+0

Mi spiace di aver scambiato qualcosa qui, probabilmente funzionerebbe con un normale ChoiceField, ma vedere la mia altra soluzione con la sottoclasse del ModelChoiceField! –

7

È possibile effettuare la propria classe campo modulo e sovrascrivere il metodo che genera l'etichetta:

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

lo usano nel modulo stesso come avete fatto con la ModelChoiceField:

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

Sì e questo è anche quello che ho scritto nella mia domanda iniziale. Questo crea etichette alternative ma etichette STATIC. Vedi la mia osservazione che recita "Per prima cosa ho pensato che potevo semplicemente scavalcare ModelChoiceField come descritto nella documentazione di Django ..." – Henri

3

In realtà la l'ultimo esempio di codice contiene errori e dovrebbe essere:

# 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 

Quindi funziona . Non c'è differenza nell'uso di "lambda obj: ..." o "def get_label (obj): ..."

Problemi correlati