Django使用自定义用户模型时如何在所有页面访问用户详情
实现方案
核心思路是通过Django自带的Session机制存储登录态,再通过上下文处理器将用户信息注入到所有模板中,同时自定义装饰器实现登录校验。
步骤1:修改登录逻辑,存储登录态到Session
验证账号密码通过后,将用户唯一ID存入Session,后续所有请求都可以通过Session判断登录状态、拉取用户信息。修改后的login函数代码如下:
def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username and password: # 捕获用户不存在的异常,避免直接报500错误 try: user = adminUser.objects.get(username=username) except adminUser.DoesNotExist: return render(request,'AdminUsers/login.html', {'error': '用户名或密码错误'}) hashed_password = user.password is_check = bcrypt.checkpw(password.encode('utf8'),hashed_password.encode('utf8')) if is_check: # 登录成功,将用户ID存入Session request.session['user_id'] = user.id # 可选:设置Session过期时间,示例为7天免登录 request.session.set_expiry(7*24*3600) return redirect(reverse('faq_index')) else: return render(request,'AdminUsers/login.html', {'error': '用户名或密码错误'}) return render(request,'AdminUsers/login.html')
步骤2:配置全局上下文处理器,所有模板自动获取用户信息
上下文处理器可以将变量自动注入到所有渲染的模板中,非常适合导航栏这种全页面通用的场景。
- 在你的APP目录下新建
context_processors.py,写入如下代码:
from .models import adminUser def get_admin_user(request): # 默认返回未登录状态 context = { "is_authenticated": False, "current_user": None } user_id = request.session.get("user_id") if user_id: try: user = adminUser.objects.get(id=user_id) context["is_authenticated"] = True context["current_user"] = user except adminUser.DoesNotExist: # 无效Session直接删除 del request.session["user_id"] return context
- 在项目
settings.py中注册这个上下文处理器,找到TEMPLATES配置项,新增你写的处理器路径(替换你的APP名称为实际APP名):
TEMPLATES = [ { # 其余原有配置保持不变 'OPTIONS': { 'context_processors': [ # 原有默认的上下文处理器保持不变 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', # 新增你的自定义上下文处理器 '你的APP名称.context_processors.get_admin_user', ], }, }, ]
步骤3:模板中直接使用变量
配置完成后,所有模板中都可以直接判断登录状态、读取用户信息,导航栏示例代码如下:
<nav> {% if is_authenticated %} <span>当前用户:{{ current_user.name }}({{ current_user.department }})</span> <a href="/logout">退出登录</a> {% else %} <a href="/login">请登录</a> {% endif %} </nav>
步骤4:自定义登录校验装饰器(可选)
如果部分页面需要登录才能访问,可以自定义装饰器替代Django内置的@login_required,代码如下:
def admin_login_required(func): def wrapper(request, *args, **kwargs): # Session中不存在user_id则跳转登录页 if not request.session.get("user_id"): return redirect("/login") return func(request, *args, **kwargs) return wrapper
使用时直接给需要校验的视图加装饰器即可:
@admin_login_required def faq_index(request): # 视图内也可以直接通过Session拿用户ID查询信息 user = adminUser.objects.get(id=request.session["user_id"]) # 其余业务逻辑
步骤5:退出登录逻辑(可选)
需要退出功能的话,清空Session即可:
def logout(request): # 清空当前用户所有Session数据 request.session.flush() return redirect("/login")
注意事项
- 确保你已经执行过
python manage.py migrate,Django会自动创建存储Session的django_session表,不需要额外操作你的admin_users表 - Session中仅存储用户ID即可,不要存储密码等敏感信息,每次需要用户详情时从数据库查询即可,高频访问场景可以自行加缓存优化
内容的提问来源于stack exchange,提问作者anonymous
相关产品推荐
相关产品推荐

