Django中如何实现特定路由访问时重定向回当前页面
Django 限制已登录用户访问注册页实现方案
实现这个逻辑有三种常用方案,按需选择即可:
方案1:自定义装饰器(最灵活,推荐)
直接写访问校验装饰器套在注册视图上即可,逻辑完全可控:
- 先写装饰器代码,建议放在项目通用的
decorators.py文件里方便复用:
from functools import wraps from django.http import HttpResponseRedirect def login_forbidden(view_func): @wraps(view_func) def wrapper(request, *args, **kwargs): # 已登录用户直接重定向回来源页,无来源时默认跳首页 if request.user.is_authenticated: redirect_url = request.META.get('HTTP_REFERER', '/') return HttpResponseRedirect(redirect_url) return view_func(request, *args, **kwargs) return wrapper
- 给注册视图加装饰器:
- 函数视图用法:
# 导入自定义装饰器 from .decorators import login_forbidden @login_forbidden def register(request): # 保留原有注册视图全部逻辑,比如表单校验、用户创建等 if request.method == "POST": form = RegisterForm(request.POST) if form.is_valid(): form.save() return redirect("login") else: form = RegisterForm() return render(request, "register.html", {"form": form})
- 类视图用法,需要搭配
method_decorator给dispatch方法加装饰:
from django.utils.decorators import method_decorator from django.views.generic import CreateView from .decorators import login_forbidden @method_decorator(login_forbidden, name="dispatch") class RegisterView(CreateView): # 保留原有类视图逻辑即可 form_class = RegisterForm template_name = "register.html" success_url = "/login/"
方案2:使用Django内置user_passes_test装饰器
不用自己写装饰器,用Django自带的权限校验装饰器也能实现,注意关闭默认的登录页重定向参数:
from django.contrib.auth.decorators import user_passes_test from django.http import HttpResponseRedirect # 校验规则:未登录用户才允许访问 def check_not_login(user): return not user.is_authenticated @user_passes_test(check_not_login, login_url='/', redirect_field_name=None) def register(request): # 原有注册视图逻辑 pass
这个方案适合不想额外写装饰器文件的简单场景,灵活度略低于自定义装饰器。
方案3:中间件全局拦截(适合多页面统一控制)
如果除了注册页,还要限制已登录用户访问登录页、找回密码页等同类路由,写中间件统一拦截更省事儿,不用给每个视图加装饰器:
- 在任意app下新建
middleware.py,写中间件逻辑:
from django.http import HttpResponseRedirect class LoginForbiddenMiddleware: def __init__(self, get_response): self.get_response = get_response # 配置所有禁止已登录用户访问的路由别名 self.block_url_names = ["register", "login", "password_reset"] def __call__(self, request): # 先判断当前路径是否在拦截列表里,再判断登录状态 if request.resolver_match and request.resolver_match.url_name in self.block_url_names: if request.user.is_authenticated: return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/")) response = self.get_response(request) return response
- 打开项目的
settings.py,找到MIDDLEWARE配置项,把这个中间件加在AuthenticationMiddleware后面,确保能正常拿到request.user对象:
MIDDLEWARE = [ # 其他默认中间件 "django.contrib.auth.middleware.AuthenticationMiddleware", # 替换成自己的中间件实际路径 "myapp.middleware.LoginForbiddenMiddleware", # 其他默认中间件 ]
注意事项
- 当用户直接在地址栏输入注册页地址访问时,
HTTP_REFERER参数为空,一定要设置兜底跳转地址(比如首页、个人中心页),避免跳转报错。 - 如果项目配置了
LOGIN_REDIRECT_URL,兜底地址可以直接取这个配置值,保持全站跳转逻辑统一。
内容的提问来源于stack exchange,提问作者SaRoz Pradhan
相关产品推荐
相关产品推荐

