在我的Flask-app中,当用户点击链接时,我尝试通过AJAX调用实现POST请求。
它就像Chromium中的魅力一样。通过httpie
请求我的视图功能时没有问题:
$ http --json POST http://127.0.0.1:5000/ctrl/remove-category id=1 csrf=1
(venv) $ : http --json POST http://127.0.0.1:5000/ctrl/remove-category id=5 csrf=1
HTTP/1.0 200 OK
Content-Length: 78
Content-Type: application/json
Date: Sat, 09 Jul 2016 09:05:20 GMT
Server: Werkzeug/0.11.8 Python/3.5.1
{
"message": "Category 'test 5' has been removed",
"status": "success"
}
但在Firefox中出现了一些奇怪的事情。我在两个FF配置文件下测试了它。他们俩都给我404错误。当点击我的第一个FF配置文件下的链接时,我得到404并且没有任何反应,即我甚至没有看到对Werkzeug服务器的POST请求,只有GET请求。
在第二个FF配置文件中,我仍然在Firebug控制台中出错:
POST http://127.0.0.1:5000/ctrl/remove-category 31ms jquery.min.js (line 6)
Error code: 404 categories (line 455)
因此发送了POST请求,我在Werkzeug日志中看到了它:
127.0.0.1 - - [09/Jul/2016 11:29:11] "POST /ctrl/remove-category HTTP/1.1" 200 -
127.0.0.1 - - [09/Jul/2016 11:29:12] "GET /ctrl/categories HTTP/1.1" 200 -
尽管如此,我仍然没有在我的AJAX中完成其他任务。成功'打电话(比如把东西保存到localStorage等)
这是我的jQuery脚本:
<script>
$('.remove').click( function() {
var data = {};
data['csrf'] = $('#csrf-removal').val()
data['id'] = $(this).data('id-removal');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", data['csrf'])
}
}
});
var remove = confirm('Are you sure?');
if (remove == true) {
$.ajax({
url: "{{ url_for('ctrl.remove_category', _external=True) }}",
type: 'post',
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: JSON.stringify(data, null, '\t'),
success: function(response) {
// message to user
var flash = "<div class='alert alert-" + response['status'] + "'>" +
"<button type='button' class='close' data-dismiss='alert'>×</button>" +
response['message'] + "</div>";
// save message to localStorage
window.onbeforeunload = function() {
localStorage.setItem('message', flash);
}
// reload the page
location.reload();
// jump to the top of the page
$('html,body').scrollTop(0);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('Error code: ' + jqXHR.status);
}
});
}
});
</script>
这是我的观点功能:
@csrf.exempt # for httpie testing
@ctrl.route('/remove-category', methods=['POST'])
#@permission_required(Permission.ADMINISTER) # httpie testing
def remove_category():
try:
id = request.json['id']
csrf = request.json['csrf']
except KeyError:
return jsonify({
'status': 'error',
'message': 'Function takes two parameters: '
'id of the entry to be removed; csrf token',
})
category = Category.query.get_or_404(id)
if category.posts.count():
status = 'warning'
message = "Category '{0}' is not empty and cannot be removed".\
format(category.title)
else:
status = 'success'
message = "Category '{0}' has been removed".\
format(category.title)
db.session.delete(category)
return jsonify({
'status': status,
'message': message,
})
我使用的是jQuery 2.0.3,Flask 0.10.1,Flask-WTF 0.9.4和Firefox 47.0。 我对与js相关的javascript和跨浏览器事物非常陌生,所以对任何帮助都表示赞赏。
P.S。我了解this topic,但使用accepts
与&#39; application / json&#39;在ajax电话中没有帮助。
更新:在Firefox中使用Chromium和Firebug中的DevTools,我将来自两个浏览器的POST请求作为cURL命令复制并比较了它们的结果:
答案 0 :(得分:0)
好的,我发现了问题。
阅读此bug report后,我升级到jQuery 2.1.1。这导致获得错误代码0而不是404.状态代码0可能意味着我的脚本在获得AJAX响应(see this SO topic)之前重新加载页面。
所以我在重新加载页面之前添加setTimeout
1秒延迟:
setTimeout(function() { // wait 1 sec
location.reload(); // reload page
$('html,body').scrollTop(0); // jump on top
}, 1000);
这就是诀窍。
P.S。 setTimeout
是一个临时解决方法,看它是否解决了问题。这样做的正确方法是使用承诺(see jQuery.when/done)