Django LoginRequiredMixin未跳转至登录页问题求助
问题分析与解决方案
核心原因
你遇到的问题本质是添加商品的请求是AJAX/JSON异步请求,而Django自带的LoginRequiredMixin和login_required装饰器返回的302重定向,浏览器不会自动触发页面跳转——AJAX请求是后台异步处理的,浏览器只会接收响应内容,不会主动改变当前页面的URL地址。
从日志能看到后端确实已经触发了重定向,但前端没有处理这个响应,所以页面停留在原地。
解决方案
方案1:前端直接处理AJAX重定向
在发送添加商品的AJAX代码中,增加状态码判断,当收到302响应时主动跳转到登录页:
// 示例:用Fetch API发送请求 fetch('/cart/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value }, body: JSON.stringify({ product_id: /* 商品ID */, selected_variations: /* 选中的规格 */, quantity: /* 数量 */ }) }) .then(response => { // 检测到重定向响应 if (response.status === 302) { window.location.href = response.headers.get('Location'); return; } return response.json(); }) .then(data => { // 处理商品添加成功后的逻辑(比如更新购物车UI) }) .catch(err => console.error('请求出错:', err));
方案2:后端适配AJAX请求,返回JSON提示
自定义一个适配AJAX的登录验证装饰器,对异步请求返回JSON格式的跳转指令,让前端更清晰地处理:
1. 自定义装饰器
在你的views.py中添加:
from django.http import JsonResponse from django.contrib.auth.decorators import login_required def ajax_login_required(view_func): @login_required(login_url='/login/') def wrapper(request, *args, **kwargs): # 判断是否为AJAX请求 if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return JsonResponse( {'redirect': f'/login/?next={request.path}'}, status=401 ) return view_func(request, *args, **kwargs) return wrapper
2. 修改CartView的post方法装饰器
替换原有的@method_decorator(login_required):
@method_decorator(ajax_login_required) def post(self, request): # 原代码保持不变
3. 前端对应处理
fetch('/cart/', { /* 请求配置 */ }) .then(response => { if (response.status === 401) { return response.json().then(data => { window.location.href = data.redirect; }); } return response.json(); }) // ...后续逻辑
额外优化:登录后返回原页面
你的登录视图目前登录成功后直接跳转到首页,没有处理next参数,用户登录后无法回到添加商品的页面。修改user_login_view:
def user_login_view(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') CustomUser = authenticate(request, username=username, password=password) if CustomUser is not None: login(request, CustomUser) messages.success(request, 'Login successful.') // 获取next参数,优先跳转到原操作页面 next_url = request.GET.get('next', 'home') return redirect(next_url) else: messages.error(request, 'Invalid username or password.') return render(request, 'users/user_login.html')
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

