¿Cuál es la causa del error de solicitud incorrecta al enviar el formulario en la aplicación Flask?

79

Después de leer muchos problemas de sonido similares y los documentos relevantes de Flask, parece que no puedo entender qué está generando el siguiente error al enviar un formulario:

400 Petición Incorrecta

El navegador (o proxy) envió una solicitud que este servidor no pudo entender.

Si bien el formulario siempre se muestra correctamente, la solicitud incorrecta ocurre cuando envío un formulario HTML que se vincula con cualquiera de estas funciones:

@app.route('/app/business', methods=['GET', 'POST'])
def apply_business():
    if request.method == 'POST':    
        new_account = Business(name=request.form['name_field'], email=request.form['email_field'], account_type="business", 
            q1=request.form['q1_field'], q2=request.form['q2_field'], q3=request.form['q3_field'], q4=request.form['q4_field'], 
            q5=request.form['q5_field'], q6=request.form['q6_field'], q7=request.form['q7_field'],
            account_status="pending", time=datetime.datetime.utcnow())
        db.session.add(new_account)
        db.session.commit()
        session['name'] = request.form['name_field']    
        return redirect(url_for('success'))
    return render_template('application.html', accounttype="business")          

@app.route('/app/student', methods=['GET', 'POST'])
def apply_student():    
    if request.method == 'POST':    
        new_account = Student(name=request.form['name_field'], email=request.form['email_field'], account_type="student", 
            q1=request.form['q1_field'], q2=request.form['q2_field'], q3=request.form['q3_field'], q4=request.form['q4_field'], 
            q5=request.form['q5_field'], q6=request.form['q6_field'], q7=request.form['q7_field'], q8=request.form['q8_field'], 
            q9=request.form['q9_field'], q10=request.form['q10_field'],
            account_status="pending", time=datetime.datetime.utcnow())
        db.session.add(new_account)
        db.session.commit()
        session['name'] = request.form['name_field']    
        return redirect(url_for('success')) 
    return render_template('application.html', accounttype="student")

La parte relevante de HTML es

<html>
<head>
    <title>apply</title>
</head>
<body>
    {% if accounttype=="business" %}
    <form action="{{ url_for('apply_business') }}" method=post class="application_form">
    {% elif accounttype=="student" %}
    <form action="{{ url_for('apply_student') }}" method=post class="application_form">     
    {% endif %} 
    <p>Full Name:</p>
    <input name="name_field" placeholder="First and Last">
    <p>Email Address:</p>
    <input name="email_field" placeholder="[email protected]">
    ...

El problema para la mayoría de la gente no era llamar GETo POST, pero estoy haciendo exactamente eso en ambas funciones, y verifiqué dos veces para asegurarme de haber importado todo lo necesario, como from flask import request. También consulté la base de datos y confirmé que las adiciones del formulario no se agregaron.

En la aplicación Flask, estaba solicitando campos de formulario que estaban etiquetados de forma ligeramente diferente en el formulario HTML. Mantener los nombres consistentes es imprescindible. Se puede leer más en esta pregunta Error de envío de formulario, frasco

zch
fuente
@SeanVieira tengo; aunque causó el mismo error, el problema pareció surgir de él tratando de enviar un formulario desde dos botones diferentes en la misma página (el problema estaba en diferenciar entre los dos) mientras que solo tengo un botón que llama a POST.
zch
5
Risitas Lo siento, debería haber sido más claro - "Flask genera un error HTTP cuando no puede encontrar una clave en los args y los diccionarios de formularios" - uno de los campos a los que está intentando acceder request.formno está allí (por ejemplo, está enviando name_feildy buscando para name_field- note la falta de ortografía), de ahí el error. (La configuración app.debug = Truele ayudará a encontrar el error).
Sean Vieira

Respuestas:

135

La solución fue simple y se descubrió en los comentarios. Como se aborda en esta pregunta, error de envío de formulario, Flask , y señalado por Sean Vieira ,

... el problema es que Flask genera un error HTTP cuando no encuentra una clave en los args y los diccionarios de formularios. Lo que Flask asume de forma predeterminada es que si está solicitando una clave en particular y no está allí, algo se dejó fuera de la solicitud y toda la solicitud no es válida.

En otras palabras, si solo un elemento de formulario que solicita en Python no se puede encontrar en HTML, entonces la solicitud POST no es válida y aparece el error, en mi caso sin ninguna irregularidad en el rastreo. Para mí, fue una falta de coherencia con la ortografía: en el HTML, etiqueté varias entradas de formulario

<input name="question1_field" placeholder="question one">

mientras que en Python, cuando se llama a un POST, tomo una forma inexistente con

request.form['question1']

mientras que, para ser coherente con los nombres de mis formularios HTML, tenía que ser

request.form['question1_field']

Espero que esto ayude.

zch
fuente
11
También puederequest.form.get('key', default_value)
OdraEncoded
1
@OdraEncoded su solución solucionó el problema. No pensé en eso, pero dict.get()devuelve, lo Noneque es más seguro que acceder usando la clave directamente, lo que puede causar KeyErrory, por lo tanto, bloquear la aplicación.
Pie 'Oh' Pah
<input name = "must_match">
jasonleonhard