Pregunta

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

Parece que los formularios de Django fueron diseñados con el caso de uso de editar datos de modo que un formulario independiente no sea 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 no está vinculado), 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 no se ha llamado a is_valid().Parece que tengo 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 existe una interfaz común para recuperar los valores del formulario entre un formulario vinculado y uno no vinculado.

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

¿Fue útil?

Solución

Si agrega este método a su clase de 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

Luego podrías reescribir tu 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'))

Otros consejos

Sin consolidar significa que no hay datos asociados con el formulario (ya sea inicial o proporcionado posteriormente), por lo que la validación puede fallar.Como se mencionó en otras respuestas (y en su propia conclusión), debe proporcionar valores iniciales y verificar tanto los datos vinculados como los valores iniciales.

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

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

Ver el documentación API de formularios oficiales, donde lo demuestran.

editar:Según las respuestas de otros usuarios, quizás esta sea 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'])

Aunque no lo he probado;¿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 conocer su nuevo descriptor de acceso "mágico".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top