Jaka jest przyczyna błędu nieprawidłowego żądania podczas przesyłania formularza w aplikacji Flask?

79

Po przeczytaniu wielu podobnie brzmiących problemów i odpowiednich dokumentów Flask nie mogę zrozumieć, co generuje następujący błąd po przesłaniu formularza:

400 złych żądań

Przeglądarka (lub serwer proxy) wysłała żądanie, którego ten serwer nie mógł zrozumieć.

Chociaż formularz zawsze wyświetla się poprawnie, złe żądanie ma miejsce, gdy wysyłam formularz HTML, który jest powiązany z jedną z tych funkcji:

@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")

Odpowiednią częścią HTML jest

<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]">
    ...

Problemem większości ludzi nie było dzwonienie GETlub POST, ale właśnie to robię w obu funkcjach i dwukrotnie sprawdziłem, czy zaimportowałem wszystko, co niezbędne, takie jak from flask import request. Przeszukałem również bazę danych i potwierdziłem, że dodatki z formularza nie zostały dodane.

W aplikacji Flask prosiłem o pola formularzy, które zostały oznaczone nieco inaczej w formularzu HTML. Utrzymanie spójności nazw jest koniecznością. Więcej można przeczytać pod tym pytaniem Błąd wysyłania formularza, Flask

zch
źródło
@SeanVieira mam; chociaż powodował ten sam błąd, problem wydawał się wynikać z tego, że próbował przesłać formularz z dwóch różnych przycisków na tej samej stronie - problem polegał na rozróżnieniu między nimi - podczas gdy ja mam tylko jeden przycisk wywołujący POST.
zch
5
Chuckles Przepraszam, powinno być bardziej jasne - „Flask zgłasza błąd HTTP, gdy nie może znaleźć klucza w args i słownikach formularzy” - nie ma jednego z pól, do których próbujesz uzyskać dostęp request.form(np. Wysyłasz name_feildi szukasz za name_field- zwróć uwagę na błąd ortograficzny), a tym samym błąd. (Ustawienie app.debug = Truepomoże ci znaleźć błąd).
Sean Vieira,

Odpowiedzi:

135

Rozwiązanie było proste i ujawnione w komentarzach. Jak wspomniano w tym pytaniu, Błąd wysyłania formularza, Flask i wskazał Sean Vieira ,

... problem polega na tym, że Flask zgłasza błąd HTTP, gdy nie może znaleźć klucza w args i słownikach formularza. Flask zakłada domyślnie, że jeśli pytasz o określony klucz, a go tam nie ma, to coś zostało pominięte w żądaniu i całe żądanie jest nieprawidłowe.

Innymi słowy, jeśli tylko jeden element formularza, którego żądasz w Pythonie, nie może zostać znaleziony w HTML, to żądanie POST jest nieprawidłowe i pojawia się błąd, w moim przypadku bez żadnych nieprawidłowości w śledzeniu. Dla mnie był to brak spójności z pisownią: w HTML oznaczałem różne dane wejściowe formularza

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

podczas gdy w Pythonie, gdy wywołano POST, chwytam nieistniejący formularz za pomocą

request.form['question1']

podczas gdy, aby było zgodne z moimi nazwami formularzy HTML, musiało być

request.form['question1_field']

Mam nadzieję, że to pomoże.

zch
źródło
11
Możesz takżerequest.form.get('key', default_value)
OdraEncoded
1
@OdraEncoded rozwiązanie rozwiązało problem. Nie pomyślałem o tym, ale dict.get()wraca, Noneco jest bezpieczniejsze niż bezpośredni dostęp za pomocą klucza, który może spowodować KeyErrorawarię aplikacji.
Ciasto „Oh” Pah
<input name = "must_match">
jasonleonhard