2009-10-20 1 views
6

A un certo punto, è necessario visualizzare un input "disabled" (disattivato da disabled="disabled") di tipo "select". Come specificato nello standard (xhtml e html4), gli input di tipo "select" non possono avere l'attributo "readonly". Si noti che questo è solo a scopo di presentazione, il valore effettivo deve finire nel POST. Così qui è quello che faccio (citando una parte della dichiarazione di forma in django):Moduli Django: il mantenimento di un campo disabilitato tra convalide

from django import forms 

_choices = ['to be', 'not to be'] 
class SomeForm(forms.Form): 
    field = forms.ChoiceField(choices=[(item, item) for item in _choices], 
        widget=forms.HiddenInput()) # the real field 

    mock_field = forms.ChoiceField(required=False, # doesn't get submitted 
         choices=[(item, item) for item in _choices], 
         label="The question", 
         widget=forms.Select(attrs={'disabled':'disabled'})) 

Poi viene inizializzato in questo modo:

initial_val = 'to be' 
form = SomeForm(ititial={'field':initial_val, 
         'mock_field':initial_val}) 

e tutto va bene. Bene, fino a quando il modulo non viene convalidato e uno degli altri campi fallisce la convalida. Quando ciò accade, il modulo viene ricaricato e i valori vengono mantenuti, ma non quello del "mock_field" - non è mai stato inviato (è disabilitato). Quindi non è conservato. Anche se ciò non influisce sull'integrità dei dati, non è ancora così soddisfacente dal punto di vista della presentazione.

C'è un modo per preservare quel campo, con il minor numero di hackery possibile? Il modulo fa parte di un django.contrib.formtools.FormWizard e i valori iniziali (e alcuni campi) vengono generati dinamicamente. Fondamentalmente, c'è già un sacco di cose in corso, sarebbe bello se fosse possibile non complicare eccessivamente le cose.

risposta

1

Bene, questa sarà la prima volta che rispondo alla mia domanda, ma ho trovato una soluzione e (mentre cerainly è un hack) funziona.

Invece di ottenere il valore iniziale dall'istanza del modulo, - self.fields['whatever'].initial sembra essere None all'interno del costruttore, sto ottenendo il valore dall'argomento parola chiave "iniziale". E poi l'ho impostato come unica scelta per il campo "simulato". In questo modo:

from django import forms 

_choices = ['to be', 'not to be'] 
class SomeForm(forms.Form): 
    field = forms.ChoiceField(choices=[(item, item) for item in _choices], 
        widget=forms.HiddenInput()) # the real field 

    mock_field = forms.ChoiceField(required=False, # doesn't get submitted 
         choices=[(item, item) for item in _choices], 
         label="The question", 
         widget=forms.Select(attrs={'disabled':'disabled'})) 

    def __init__(self, *args, **kwargs): 
     super(SomeForm, self).__init__(*args, **kwargs) 
     mock_initial = kwargs['initial']['field'] 
     self.fields['mock_field'].choices = [(mock_initial, mock_initial),] 

Questo probabilmente ha bisogno di una gestione degli errori. Ovviamente, questo non funzionerà se non viene fornito il valore iniziale per l'attuale field.

3

I browser non contengono campi disattivati.

Si può provare a copiare field s valore iniziale a mock_field in del vostro forma di codice __init__

def __init__(self, *args, **kwargs): 
    super(SomeForm, self).__init__(*args, **kwargs) 
    mock_initial = self.fields['field'].initial 
    self.fields['mock_field'].initial = mock_initial 

non è testato. Normalmente saresti preoccupato per lo form.data, ma in questo caso non sarà diverso da initial

+0

Bene, io, certamente, so che i campi disabilitati non vengono pubblicati (perché solo i controlli riusciti vengono postati e i campi disabilitati non hanno esito positivo). Sto andando a testare il tuo approccio ora. Sembra abbastanza convincente. – shylent