Django中XMLHttpRequest请求后带消息重定向失效及Cookie问题解决
问题分析与解决方案
核心问题
- 重定向不生效:你用XMLHttpRequest发起异步POST请求,后端返回的
redirect响应只会被XHR对象处理(自动请求重定向后的URL),但不会触发浏览器页面跳转——这是XHR的特性,它不会主动刷新或跳转当前页面。 - messages Cookie过期:旧的
messagesCookie已过期,Django尝试设置新的messages Cookie时,浏览器拒绝接收过期的旧Cookie,或者Cookie的有效期配置存在问题。
解决方案
1. 调整后端逻辑:返回JSON而非直接重定向
后端不再直接返回redirect,而是返回包含跳转地址和消息的JSON数据,同时处理过期Cookie的删除:
from django.http import JsonResponse from django.urls import reverse from django.contrib.messages import get_messages def newSeq(request): if request.method == "POST": # 处理过期的messages Cookie(如果存在) response_data = { 'redirect_url': reverse('newSeq'), 'message': 'Ricevuto' } response = JsonResponse(response_data) if 'messages' in request.COOKIES: # 删除过期的messages Cookie response.delete_cookie('messages') return response # GET请求时,正常渲染页面并传递messages messages_list = [m.message for m in get_messages(request)] return render( request, 'dashboard/newSeq.html', { 'messages': messages_list } )
2. 修改前端代码:处理响应并手动跳转
给XMLHttpRequest添加onload事件,接收后端返回的JSON数据,完成页面跳转并按需显示消息:
var xmlhttp = new XMLHttpRequest(); var theUrl = "newSeq"; xmlhttp.open("POST", theUrl); xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); xmlhttp.setRequestHeader("X-CSRFToken", csrftoken); // 添加响应处理逻辑 xmlhttp.onload = function() { if (this.status >= 200 && this.status < 300) { const response = JSON.parse(this.responseText); // 手动跳转到目标页面 window.location.href = response.redirect_url; // 可选:跳转前显示消息 alert(response.message); } }; xmlhttp.send(JSON.stringify(my_json));
3. 可选:保留Django Messages框架的方案
如果想继续使用Django的messages框架,可让后端在XHR请求中重置有效Cookie,前端跳转后在页面渲染messages:
from django.shortcuts import redirect from django.http import JsonResponse from django.contrib.messages import get_messages def newSeq(request): if request.method == "POST": messages.success(request, "Ricevuto") redirect_response = redirect("newSeq") # 删除过期的messages Cookie(如果存在) if 'messages' in request.COOKIES: redirect_response.delete_cookie('messages') # 返回跳转地址给前端 return JsonResponse({ 'redirect_url': redirect_response.url }) messages_list = [m.message for m in get_messages(request)] return render( request, 'dashboard/newSeq.html', { 'messages': messages_list } )
同时在前端模板中添加messages渲染逻辑:
{% if messages %} {% for message in messages %} <div class="alert alert-success">{{ message }}</div> {% endfor %} {% endif %}
关键说明
- 删除特定Cookie:Django的所有
HttpResponse子类(包括JsonResponse、redirect返回的响应)都支持delete_cookie()方法,传入Cookie名称即可删除对应Cookie,比如response.delete_cookie('messages')。 - XHR请求的重定向限制:异步请求不会触发页面跳转,必须通过前端
window.location.href手动实现页面跳转。
内容的提问来源于stack exchange,提问作者NicoCaldo
相关产品推荐
相关产品推荐

