2013-03-21 12 views
29
class LoginForm(forms.Form): 
    nickname = forms.CharField(max_length=100) 
    username = forms.CharField(max_length=100) 
    password = forms.CharField(widget=forms.PasswordInput) 


class LoginFormWithoutNickname(LoginForm): 
    # i don't want the field nickname here 
    nickname = None #?? 

C'è un modo per raggiungere questo obiettivo?Django: rimuovere un campo da una sottoclasse di modulo

Nota: non ho uno ModelForm, quindi la classe Meta con exclude non funziona.

risposta

54

È possibile modificare i campi in una sottoclasse sovrascrivendo il metodo init :

class LoginFormWithoutNickname(LoginForm): 
    def __init__(self, *args, **kwargs): 
     super(LoginFormWithoutNickname, self).__init__(*args, **kwargs) 
     self.fields.pop('nickname') 
+0

ringraziamento, si prega di modificare il __init __ (self) '' a '__init __ (self, * args, ** kwargs)' – apelliciari

+0

Done, buona pesca. – garnertb

+4

Non ha funzionato con un modulo di amministrazione in linea, i modelli cercano di renderli comunque, e ottengo un KeyError. – lvella

9

Django 1,7 affrontato questo nel commettere b16dd1fe019 i biglietti #8620. In Django 1.7, diventa possibile fare nickname = None nella sottoclasse come suggerisce l'OP. Dalle modifiche alla documentazione nel commettere: out opt-

E 'possibile da un Field ereditati da una classe padre da shadowing esso. Mentre qualsiasi valore non Field funziona per questo scopo, si consiglia di utilizzare None per rendere esplicito che un campo viene annullato.

+0

Funziona? Come "annullato" significa che avrà valore Nessuno? Poiché ho provato a utilizzare "meta -> exclude = []" funziona come mi aspetto, "il tuo" modo usa un valore predefinito per il campo, uguale a Nessuno – Gromish

+2

Nota che questo funzionerà solo quando il campo è dichiarato dal genitore classe. In generale, questo non funzionerà con 'ModelForm's. – SaeX

+0

Ho provato questa soluzione per rimuovere 'assigned_to' in TicketForm. Il campo è scomparso dal modulo come previsto, ma ora genera un errore durante la creazione del ticket. Il valore predefinito è dato ma non è stato pulito_data. È un modo per nascondere questo campo specifico dal modulo mentre verrà comunque inviato tramite clean_data? –

3

Ho trovato che, si prega di commentare se interessati.

(in Django 1.7.4) forme estendentisi, con codice seguente:

class MyForm(forms.ModelForm): 

    def __init__(self, *args, **kwargs): 
     super(MyForm, self).__init__(*args, **kwargs) 

     for key, field in self.fields.iteritems(): 
      self.fields[key].required = False 

    class Meta: 
     model = MyModel 
     exclude = [] 

    field_1 = forms.CharField(label="field_1_label") 
    field_2 = forms.CharField(label="field_2_label", widget=forms.Textarea(attrs={'class': 'width100 h4em'}),) 
    field_3 = forms.CharField(label="field_3_label", widget=forms.TextInput(attrs={'class': 'width100'}),) 
    field_4 = forms.ModelChoiceField(label='field_4_label', queryset=AnotherModel.objects.all().order_by("order")) 

class MyForm_Extended_1(MyForm): 
    field_1 = None 


class MyForm_Extended_2(MyForm): 
    class Meta: 
     model = MyModel 
     exclude =[ 
        'field_1', 
       ] 

MyForm_Extended_1 impostato Campo_1 come Nessuno, (la colonna in dB viene aggiornato come Null)

MyForm_Extended_2 ignorano campo (ignora la colonna in db durante il salvataggio)

Quindi, per il mio scopo, uso il secondo metodo.

1

Non mi piaceva il fatto (o così ho capito) che l'esclusione di un campo nella seconda classe usando "classe Meta:" risulta ancora nel campo inutilizzato che si trova nel db.

Forse il modo più semplice è definire una classe astratta con i campi condivisi da entrambe le classi. Quindi le due classi originali sopra diventano sottoclassi di questa nuova classe. Quindi l'esempio dato all'inizio di questo thread potrebbe sembrare il seguente. È un po 'più codice, ma in questo modo si estende una sottoclasse piuttosto che un'esclusione (incompleta) da una super classe.

class LoginForm_Common(forms.Form): 
    username = forms.CharField(max_length=100) 
    password = forms.CharField(widget=forms.PasswordInput) 
    class Meta: 
     abstract = True 

class LoginForm(LoginForm_Common): 
    nickname = forms.CharField(max_length=100) 

class LoginFormWithoutNickname(LoginForm_Common): 
    pass 
Problemi correlati