我正在制作用于发送电子邮件的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工具上获得的东西:
答案 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请求有效负载中发送email
和password
个密钥,你发送emailInput
和passwordInput
参数,这就是为什么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。