如何修复Django项目ERR_TOO_MANY_REDIRECTS重定向错误
ERR_TOO_MANY_REDIRECTS 问题排查与修复
这个重定向死循环问题和你贴的视图逻辑直接相关,核心原因是重定向规则形成了闭环,和Cookie无关,按下面的顺序排查即可:
核心问题点
- 最高发原因:根路径
/和登录路由的跳转逻辑形成闭环
你现有视图里,登录成功、注册成功、登出三个操作最终都会跳转到根路径/,如果你的根路径视图满足以下任意一种情况,就会触发无限重定向:- 根路径视图加了
@login_required登录校验装饰器,同时settings.py里的LOGIN_URL被错误配置成了/,逻辑变成:未登录访问/→被拦截要求跳登录页→登录页地址就是/→再次被拦截,无限循环 - 根路径视图手写了登录校验,逻辑写反成「未登录跳根路径」「已登录跳登录页」,直接形成自循环
- 根路径视图加了
- 次高发原因:登录/注册视图被误加登录校验
如果你给login、reg两个本身给未登录用户开放的视图加了@login_required装饰器,同时LOGIN_URL指向login路由本身,访问登录页时会被拦截要求跳登录页,直接触发死循环。 - 易忽略的逻辑缺失:登录/注册页没有拦截已登录用户
你现在写的login、reg视图没有判断用户登录状态,不管用户是不是已经登录,GET请求都会直接渲染页面。如果你配了全局逻辑(比如自定义中间件)要求「已登录用户不能访问登录页,自动跳根路径」,就会和根路径的「未登录跳登录页」规则形成跳转闭环。
修复步骤
- 先修正配置:打开
settings.py,把LOGIN_URL明确指向你的登录路由,比如你的登录页路由是path('login/', views.login, name='login'),就设置LOGIN_URL = '/login/',绝对不要设成根路径/。 - 移除
login、reg两个视图上的@login_required装饰器,这两个页面不需要登录校验。 - 给
login、reg视图补上已登录用户拦截逻辑,避免重复跳转,参考修改后的代码:
from django.shortcuts import redirect, render from django.contrib.auth.models import User, auth from django.contrib import messages def reg(request): # 已登录用户直接跳首页,避免无效访问和循环 if request.user.is_authenticated: return redirect('/') if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] cpassword = request.POST['cpassword'] if password == cpassword: # 用exists()判断用户名是否存在,查询效率更高 if User.objects.filter(username=username).exists(): messages.info(request, 'Username taken') return redirect('registration') else: user = User.objects.create_user(username=username, password=password) user.save() return redirect('login') else: messages.info(request, 'Passwords not matching') return redirect('registration') else: return render(request, 'registration.html') def login(request): # 已登录用户直接跳首页 if request.user.is_authenticated: return redirect('/') if request.method == "POST": username = request.POST['username'] password = request.POST['password'] user = auth.authenticate(username=username, password=password) if user is not None: auth.login(request, user) return redirect('/') else: messages.info(request, 'Invalid credentials') return redirect('login') else: return render(request, 'login.html') def logout(request): auth.logout(request) return redirect('/')
- 检查根路径
/对应的视图逻辑,未登录用户的跳转目标必须明确是/login/路由,不能跳回根路径自身。
额外说明:你原代码里
reg视图POST分支最后那句return redirect('/')是永远执行不到的死代码——前面的if/else分支已经覆盖了所有密码匹配/不匹配的场景,都会提前return,这句可以直接删掉。开头导入的from email import message、from wsgiref.util import request_uri两个模块全程没用到,也可以删掉减少冗余。
内容的提问来源于stack exchange,提问作者zakharchik
相关产品推荐
相关产品推荐

