Jquery 烧瓶及;AJAX:加载资源失败:服务器响应状态为400(错误请求)

Jquery 烧瓶及;AJAX:加载资源失败:服务器响应状态为400(错误请求),jquery,ajax,flask,jinja2,Jquery,Ajax,Flask,Jinja2,我正在申请发送电子邮件。在我决定实现一点AJAX以使其更具交互性之前,它工作得相当不错 我经常会出现400个错误,我尝试了很多组合,但都没有效果 有人告诉我问题出在CSRF令牌中,但当我放入@CSRF.empturedecorator时,它仍然不起作用。请帮忙 以下是源代码: 1)烧瓶: from flask import Flask, render_template, url_for, redirect, request, jsonify from flask_bootstrap import

我正在申请发送电子邮件。在我决定实现一点AJAX以使其更具交互性之前,它工作得相当不错

我经常会出现400个错误,我尝试了很多组合,但都没有效果

有人告诉我问题出在CSRF令牌中,但当我放入
@CSRF.empture
decorator时,它仍然不起作用。请帮忙

以下是源代码:

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)
{% 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 %}
$('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();

});
2)HTML:

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)
{% 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 %}
$('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开发工具上得到的信息:

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)
{% 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 %}
$('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();

});

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

    data : {
        firstnameInput : $('#firstnameInput').val(),
        lastnameInput : $('#lastnameInput').val(),
        emailInput : $('#emailInput').val(),
        passwordInput : $('#passwordInput').val(),
        messageInput : $('#messageInput').val()
    }
并尝试在
过程中处理以下参数
路由:

emailInput = request.form['email']
passwordInput = request.form['password']
但是,在ajax请求有效负载中,您不发送
电子邮件
密码
键,而是发送
电子邮件输入
密码输入
参数,因此Flask会以
400
状态代码响应您-在路由函数中尝试使用的POST body中没有此类参数

您的代码应该是:

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

    emailInput = request.form['emailInput']
    passwordInput = request.form['passwordInput']
就这样

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

@app.route('/process/', methods=['POST'])
为了避免302重定向到Flask执行的
/process/
url


还建议使用
request.form.get('param')
而不是
request.form['param']
,因为
.get()
函数在dict中没有指定键时返回None,而不是引发异常。

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

    data : {
        firstnameInput : $('#firstnameInput').val(),
        lastnameInput : $('#lastnameInput').val(),
        emailInput : $('#emailInput').val(),
        passwordInput : $('#passwordInput').val(),
        messageInput : $('#messageInput').val()
    }
并尝试在
过程中处理以下参数
路由:

emailInput = request.form['email']
passwordInput = request.form['password']
但是,在ajax请求有效负载中,您不发送
电子邮件
密码
键,而是发送
电子邮件输入
密码输入
参数,因此Flask会以
400
状态代码响应您-在路由函数中尝试使用的POST body中没有此类参数

您的代码应该是:

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

    emailInput = request.form['emailInput']
    passwordInput = request.form['passwordInput']
就这样

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

@app.route('/process/', methods=['POST'])
为了避免302重定向到Flask执行的
/process/
url

还建议使用
request.form.get('param')
而不是
request.form['param']
,因为
.get()
函数在dict中没有指定键时返回None,而不是引发异常