2009-10-20 15 views
6

En algún momento necesito mostrar una entrada "disabled" (atenuada por disabled="disabled") del tipo "select". Como se especifica en el estándar (xhtml y html4), las entradas del tipo "select" no pueden tener el atributo "readonly". Tenga en cuenta que esto es solo para fines de presentación, el valor real debe terminar en el POST. Así que aquí está lo que hago (citando a una parte de la declaración de la forma en Django):Formularios Django: hacer que un campo deshabilitado persista entre las validaciones

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'})) 

A continuación se inicializa como esto:

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

y todo está bien. Bueno, hasta que el formulario se valida y uno de los otros campos falla la validación. Cuando esto sucede, el formulario se vuelve a cargar y los valores se conservan, pero no el del "mock_field": nunca se envió (está deshabilitado). Por lo tanto, no se conserva. Si bien esto no afecta la integridad de los datos, aún no es tan bueno para la presentación.

¿Hay alguna manera de preservar ese campo, con la menor cantidad de hackers posible? El formulario forma parte de un django.contrib.formtools.FormWizard y los valores iniciales (y algunos campos) se generan dinámicamente. Básicamente, ya están sucediendo muchas cosas, sería fantástico si fuera posible no complicar demasiado las cosas.

Respuesta

1

Bueno, esta será la primera vez que responda mi pregunta, pero encontré una solución y (mientras cerainly es un truco) funciona.

En lugar de obtener el valor inicial de la instancia del formulario, - self.fields['whatever'].initial parece ser None dentro del constructor, obtengo el valor del argumento de palabra clave "inicial". Y luego lo configuré como la única opción para el campo "simulacro". De esta manera:

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),] 

Esto probablemente necesita un cierto manejo de errores. Obviamente, esto no funcionará si el valor inicial no se proporciona para el field real.

3

Los navegadores no POST desactivan los campos.

Usted puede tratar de copiar field s valor inicial a mock_field en el Código __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 

de su formulario no está probado. Normalmente también le preocuparía el form.data, pero en este caso no será diferente de initial

+0

Bueno, yo, sin duda, sé que los campos desactivados no se publican (porque solo se publican controles exitosos y los campos desactivados nunca tienen éxito). Voy a probar tu enfoque ahora. Parece bastante convincente. – shylent

Cuestiones relacionadas