You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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绕过地址提交,可以新增全局中间件做统一拦截:

  1. 新建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)
  1. 在settings.py的MIDDLEWARE列表中注册该中间件:
MIDDLEWARE = [
    # 其他原有中间件
    'your_app_name.middleware.FirstLoginCheckMiddleware',
]

关于信号方案的说明

你提到的user_logged_in信号可以用来记录登录状态,但无法直接处理跳转逻辑,跳转依然需要在视图或中间件中实现,因此上面的方案更直接,也完全兼容你原有的Session有效期自定义逻辑,不需要额外适配。

内容的提问来源于stack exchange,提问作者Shreyash mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 14:36:03