2008-09-16 14 views
7

Tengo un informe web que usa un formulario Django (formularios nuevos) para los campos que controlan la consulta utilizada para generar el informe (fecha de inicio, fecha de finalización, ...). El problema que estoy teniendo es que la página debería funcionar utilizando los valores iniciales del formulario (sin consolidar), pero no puedo acceder al campo clean_data a menos que llame a is_valid(). Pero is_valid() siempre falla en formularios independientes.Cómo usar los valores del formulario desde un formulario independiente

Parece que los formularios de Django se diseñaron con el uso de datos de edición de modo que una forma independiente no es realmente útil para nada más que mostrar HTML.

Por ejemplo, si tengo:

if request.method == 'GET': 
    form = MyForm() 
else: 
    form = MyForm(request.method.POST) 

if form.is_valid(): 
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date']) 

is_valid() fallará si se trata de un GET (ya que es sin consolidar), y si lo hago:

if request.method == 'GET': 
    form = MyForm() 
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date']) 
else: 
    form = MyForm(request.method.POST) 
    if form.is_valid(): 
     do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date']) 

la primera llamada a do_query desencadena excepciones en form.cleaned_data, que no es un campo válido porque is_valid() no se ha llamado. Parece como si tuviera que hacer algo como:

if request.method == 'GET': 
    form = MyForm() 
    do_query(form['start_date'].field.initial, form['end_date'].field.initial) 
else: 
    form = MyForm(request.method.POST) 
    if form.is_valid(): 
     do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date']) 

es decir, no hay una interfaz común para recuperar los valores de la forma entre una forma unida y uno no unido.

¿Alguien ve una manera más limpia de hacer esto?

Respuesta

4

Si añade este método a la clase formulario:

def get_cleaned_or_initial(self, fieldname): 
     if hasattr(self, 'cleaned_data'): 
      return self.cleaned_data.get(fieldname) 
     else: 
      return self[fieldname].field.initial 

que podría volver a escribir el código como:

if request.method == 'GET': 
    form = MyForm() 
else: 
    form = MyForm(request.method.POST) 
    form.is_valid() 

do_query(form.get_cleaned_or_initial('start_date'), form.get_cleaned_or_initial('end_date')) 
0

Puede pasar un diccionario de valores iniciales a su formulario:

if request.method == "GET": 
    # calculate my_start_date and my_end_date here... 
    form = MyForm({ 'start_date': my_start_date, 'end_date': my_end_date}) 
... 

Véase el official forms API documentation, en el que demuestran esto.

edición: En base a las respuestas de otros usuarios, tal vez esta es la solución más limpia:

if request.method == "GET": 
    form = MyForm() 
    form['start_date'] = form['start_date'].field.initial 
    form['end_date'] = form['end_date'].field.initial 
else: 
    form = MyForm(request.method.POST) 
if form.is_valid(): 
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date']) 

No he probado esto, sin embargo; ¿Alguien puede confirmar que esto funciona? Creo que esto es mejor que crear un nuevo método, porque este enfoque no requiere otro código (posiblemente no escrito por usted) para saber sobre su nuevo acceso "mágico".

+0

Sí, pero los valores predeterminados no se definen con el formulario (como con initial = value en las declaraciones de campo). Si usa el formulario en varios lugares, tendrá que repetir sus valores predeterminados. – davidavr

1

Sin consolidar significa que no hay datos asociados con la forma (ya sea inicial o proporcionada más tarde), por lo que la validación puede fallar. Como se menciona en otras respuestas (y en su propia conclusión), debe proporcionar valores iniciales y verificar tanto los datos ligados como los valores iniciales.

El caso de uso para formularios es la validación de procesamiento de formulario y, por lo que debe tener algunos datos para validar antes de acceder al cleaned_data.

Cuestiones relacionadas