烧瓶& AJAX:无法加载资源:服务器响应状态为400(BAD REQUEST)

时间:2017-11-17 13:45:56

标签: jquery ajax flask jinja2

我正在制作用于发送电子邮件的Flask应用程序。它工作得很好,直到我决定实现一点点AJAX以使其更具交互性。

我经常得到400 ERROR,我尝试了很多组合,但注意到了。

有些人告诉我问题出在CSRF令牌中,但是当我把@csrf.exempt装饰器放进去时,它仍然无效。请帮忙!

以下是源代码:

1)烧瓶:

from flask import Flask, render_template, url_for, redirect, request, jsonify
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_mail import Mail, Message
from flask_wtf.csrf import CSRFProtect
from wtforms import StringField, PasswordField, BooleanField, TextAreaField
from wtforms.validators import InputRequired, Email, Length, AnyOf, Regexp
from flask_wtf import FlaskForm

app = Flask(__name__)
app.config['SECRET_KEY'] = '**********'

mail = Mail(app)
Bootstrap(app)
csrf = CSRFProtect(app)

class LoginForm(FlaskForm):
    email = StringField('Email *', _name='email', validators=[InputRequired(), Email(message='I don\'t like your email.')], render_kw={"placeholder": "Please enter your email"})
    password = PasswordField('Password *', _name='password', validators=[InputRequired(), Length(min=5, max=10), AnyOf(['secret', 'password'])], render_kw={"placeholder": "Please enter your password"})

app.config.update(
    DEBUG = True,
    # EMAIL SETTINGS
    MAIL_SERVER = 'smtp.gmail.com',
    MAIL_PORT = 465,
    MAIL_USE_SSL = True,
    MAIL_USERNAME = 'jakov.kusic92@gmail.com',
    MAIL_PASSWORD = '********'
)

@csrf.exempt
@app.route('/', methods=['GET', 'POST'])
def mailForm():
    form = LoginForm()
    return render_template('loginForm.html', form=form)

@csrf.exempt
@app.route('/process', methods=['POST'])
def process():

    emailInput = request.form['email']
    passwordInput = request.form['password']


    str = 'Hello'
    msg = Message(
        subject=str,
        sender='jakov.kusic92@gmail.com',
        recipients=['jakov.kusic@gmail.com']
    )
    msg.body = """
    NEW USER INFO:
    Email: {}
    Password: {}
    """.format(emailInput, passwordInput)

    if emailInput and passwordInput:
        # mail.send(msg)
        return jsonify({'firstname' : emailInput, 'lastname' : passwordInput})

    return jsonify({'error' : 'Missing data!'})

if __name__ == '__main__':
    app.run(debug=True)

2)HTML:

{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}
WTForms
{% endblock %}

{% block head %}
    {{ super() }}
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    <script src="https://code.jquery.com/jquery-2.2.4.js"></script>
    <script src="{{ url_for('static', filename='form.js') }}" type="text/javascript"></script>

{% endblock %}

{% block content %}
<div class="container">

    <br><br> <!-- br tags are here used for vertical alingment -->
    <div class="col-md-4 col-md-offset-4 col-sm-8 col-sm-offset-2">
        <div class="well">
            <br>
            <h1 class="text-center">Welcome to the database website</h1>
            <br>
            <h2>Please enter your data below:</h2>
            <form>
                <dl>
                    {{ wtf.quick_form(form)}}
                    <input type="submit" value="Login" class="btn btn-info">
                </dl>
            </form>
            <div class="row">
                <div class="col-md-12">
                    <p class="text-muted"><strong>*</strong> These fields are required.</p>
                </div>
            </div>
            <div id="successAlert" class="alert alert-success" role="alert" style="display:none;"></div>
            <div id="errorAlert" class="alert alert-danger" role="alert" style="display:none;"></div>
        </div>
    </div>
</div>
{% endblock %}

3)JS:

$('form').on('submit', function(event) {

    $.ajax({
        data : {
            firstnameInput : $('#firstnameInput').val(),
            lastnameInput : $('#lastnameInput').val(),
            emailInput : $('#emailInput').val(),
            passwordInput : $('#passwordInput').val(),
            messageInput : $('#messageInput').val()
        },
        type : 'POST',
        headers: {
            'Cache-Control': 'no-cache, no-store, must-revalidate',
            'Pragma': 'no-cache',
            'Expires': '0'
        },
        url : '/process',
        dataType: "json",
        contentType: "application/json"
    })
    .done(function(data) {
        $('#successAlert').text(data.firstname + data.lastname).show();
        $('#errorAlert').hide();
    });

    event.preventDefault();

});

这就是我在CHROME DEV工具上获得的东西:

enter image description here

1 个答案:

答案 0 :(得分:1)

您将带有以下有效负载的ajax请求发送到/process网址:

    data : {
        firstnameInput : $('#firstnameInput').val(),
        lastnameInput : $('#lastnameInput').val(),
        emailInput : $('#emailInput').val(),
        passwordInput : $('#passwordInput').val(),
        messageInput : $('#messageInput').val()
    }

您尝试在process路线中处理以下参数:

emailInput = request.form['email']
passwordInput = request.form['password']

但是你没有在ajax请求有效负载中发送emailpassword个密钥,你发送emailInputpasswordInput参数,这就是为什么Flask用{回应你'的原因{1}}状态代码 - 您尝试在路由功能中使用POST主体中没有此类参数。

您的代码应为:

400

就是这样。

此外,建议在网址末尾使用“/”:

@app.route('/process/', methods=['POST'])
def process():

    emailInput = request.form['emailInput']
    passwordInput = request.form['passwordInput']

以避免302重定向到Flask所做的@app.route('/process/', methods=['POST']) 网址。

建议使用/process/代替request.form.get('param'),因为如果dict中没有指定的键而不是引发异常,request.form['param']函数将返回None。