Django如何判断用户首次登录并实现不同场景的页面跳转
实现方案
步骤1:新增首次登录标记字段
首先需要给用户模型增加字段标记是否是首次登录,推荐通过关联的用户资料模型实现,示例代码:
from django.db import models from django.contrib.auth.models import User class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile") is_first_login = models.BooleanField(default=True, verbose_name="是否首次登录") # 其他用户自定义字段
你也可以直接在自定义的User模型中添加该字段,效果一致。同时需要新增post_save信号,实现创建用户时自动生成关联的UserProfile实例:
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: UserProfile.objects.create(user=instance) @receiver(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): instance.profile.save()
步骤2:修改登录视图增加跳转判断
不需要改动原有remember_me的Session有效期逻辑,只需要在用户登录成功后新增首次登录判断即可,修改后的my_login视图代码:
def my_login(request): if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): username = form.cleaned_data["username"] password = form.cleaned_data["password"] remember_me = form.cleaned_data['remember_me'] user = authenticate(username=username, password=password) if user: login(request, user) # 原有Session有效期逻辑完全保留 if not remember_me: request.session.set_expiry(0) else: request.session.set_expiry(1209600) # 新增首次登录跳转判断 if user.profile.is_first_login: return redirect('accounts:add_address', username=user.username) else: return redirect('accounts:home') else: return redirect('accounts:login') else: return redirect('accounts:register') else: form = LoginForm() return render(request, "login.html", {'form': form})
步骤3:修改地址提交视图更新首次登录标记
用户提交地址成功后,需要把首次登录标记改为False,修改后的add_address视图代码:
@login_required def add_address(request, username): if request.method == 'POST': form = Addressform(request.POST) if form.is_valid(): form = form.save(commit=False) form.user = request.user form.save() # 标记用户已完成首次登录 request.user.profile.is_first_login = False request.user.profile.save() return redirect('accounts:home') else: form = Addressform() return render(request, 'add_address.html', {'form': form})
可选优化:新增中间件防止绕过地址提交
如果需要避免用户手动输入其他URL绕过地址提交,可以新增全局中间件做统一拦截:
- 新建
middleware.py文件:
from django.shortcuts import redirect from django.urls import reverse class FirstLoginCheckMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 排除无需拦截的路径:登录、注册、地址提交页、静态资源等 exempt_paths = [ reverse('accounts:login'), reverse('accounts:register'), reverse('accounts:add_address', args=[request.user.username]) if request.user.is_authenticated else '', ] if request.path in exempt_paths or request.path.startswith('/static/'): return self.get_response(request) # 已登录用户判断是否首次登录 if request.user.is_authenticated and request.user.profile.is_first_login: return redirect('accounts:add_address', username=request.user.username) return self.get_response(request)
- 在
settings.py的MIDDLEWARE列表中注册该中间件:
MIDDLEWARE = [ # 其他原有中间件 'your_app_name.middleware.FirstLoginCheckMiddleware', ]
关于信号方案的说明
你提到的user_logged_in信号可以用来记录登录状态,但无法直接处理跳转逻辑,跳转依然需要在视图或中间件中实现,因此上面的方案更直接,也完全兼容你原有的Session有效期自定义逻辑,不需要额外适配。
内容的提问来源于stack exchange,提问作者Shreyash mishra
相关产品推荐
相关产品推荐

