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

Django多用户类型登录重定向异常问题求助

Django用户登录后重定向异常排查与修复

我正在开发一个包含房东(Landlord)、经纪人(Agent)和潜在租户(Prospect)三类用户的Django项目,需求是用户登录后根据其类型跳转到对应页面。但当前代码存在问题:合法用户登录后,视图仍会将其重定向回登录页面,需要排查修复。

模型代码

class Landlord(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    is_verified = models.BooleanField(default=False) 

    def __str__(self):
        return self.user.username

class Agent(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    is_verified = models.BooleanField(default=False)

    def __str__(self):
        return self.user.username

class Prospect(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='prospect_profile')
    payment_ref = models.CharField(max_length=100, blank=True, null=True)
    payment_status = models.BooleanField(default=False)
    properties = models.ManyToManyField('Property', through='Tenancy')

    def __str__(self):
        return self.user.username

    def become_tenant(self, property):
        if self.payment_status:
            tenant = Tenancy.objects.create(tenant=self, property=property, agent=property.agent, landlord=property.landlord)
            return tenant
        else:
            return None

class Tenancy(models.Model):
    tenant = models.ForeignKey(Prospect, on_delete=models.CASCADE)
    property = models.ForeignKey('Property', on_delete=models.CASCADE)
    agent = models.ForeignKey('Agent', on_delete=models.CASCADE)
    landlord = models.ForeignKey('Landlord', on_delete=models.CASCADE)
    start_date = models.DateField()
    end_date = models.DateField()

    def __str__(self):
        return f'{self.tenant} - {self.property}'

    class Meta:
        verbose_name_plural = 'Tenancies'

视图代码

def index(request):
    user = request.user

    if user:
        # Check if User Profile is completed with new image uploaded 
        def profile_complete(profile):
                    return (
                profile.full_name is not None and profile.full_name != '' and
                profile.phone_number is not None and profile.phone_number != '' and
                profile.email is not None and profile.email != '' and
                profile.address is not None and profile.address != '' and
                profile.image is not None and profile.image != 'avatar.jpg'
            )
        #Check if user is either a Landlord, Agent, or Prospect and Profile is completed and they have unread messages
        if Landlord.user == user or Agent.user == user:
            try:
                profile = Profile.objects.select_related('user').get(user=user)
                if not profile_complete(profile):
                    return redirect('account-profile-update')
                elif user.landlord == 'landlord':
                    # Get all logged in landlord Properties
                    landlord_properties = Property.objects.filter(landlord__user=user)
                    if not landlord_properties.exists():
                        return redirect('add-property')
                    # Check if landlord has any notifications with status False
                    elif Message.objects.filter(property__landlord=user.landlord, status=False).exists():
                        return redirect('inbox')
                    else:
                        return redirect('property-listing')
                elif Agent.user == user:
                    # Get all the logged in Agent Properties
                    agent_properties = Property.objects.filter(agent__user=user)
                    if not agent_properties.exists():
                        return redirect('add-property')
                    # Check ifagent has any notifications with status False
                    elif Message.objects.filter(property__agent=user.agent, status=False).exists():
                        return redirect('inbox') 
                    else:
                        return redirect('property-listing')
            except (Landlord.DoesNotExist, Agent.DoesNotExist): 
                pass
        #Check if user is Prospect and Profile is completed
        elif Prospect.user == user:
            try:
                #Match the logged in user with users in the Profile DB
                prospect_profile = Profile.objects.get(user=user)
                #Check if Prospect Profile is completed and redirect
                if not profile_complete(prospect_profile):
                    return redirect('account-profile-update')
                elif Message.objects.filter(recipient=user, status=False).exists():
                    return redirect('inbox')
                else:
                    return redirect('listings')
            except Prospect.DoesNotExist:
                pass

    request.session['user_type'] = 'default'
    return redirect('account-login')

问题排查与修复

核心问题分析

  1. 用户验证逻辑无效:if user: 永远为真——即使未登录,request.user 也是匿名用户对象,导致后续逻辑执行出错后直接走到重定向登录的代码。正确判断应为 if user.is_authenticated:。
  2. 用户类型判断逻辑错误:
    • Landlord.user == user 是拿模型类的字段和用户对象比较,完全不成立,应该用 hasattr(user, 'landlord') 或try-except判断用户是否关联了对应实例。
    • user.landlord == 'landlord' 是拿Landlord实例和字符串比较,逻辑错误,无需此判断,确认用户是房东后直接执行对应逻辑即可。
  3. 异常处理后无后续动作:try块抛出异常(比如用户没有对应Profile)后,pass 之后没有任何处理,直接走到最后重定向登录。
  4. Prospect判断同样错误:Prospect.user == user 也是模型字段和用户对象比较,逻辑无效。

修复后的视图代码

def index(request):
    user = request.user

    # 仅处理已登录用户
    if user.is_authenticated:
        def profile_complete(profile):
            return (
                profile.full_name and profile.full_name.strip() != '' and
                profile.phone_number and profile.phone_number.strip() != '' and
                profile.email and profile.email.strip() != '' and
                profile.address and profile.address.strip() != '' and
                profile.image and profile.image != 'avatar.jpg'
            )
        
        # 检查是否为房东
        try:
            landlord = user.landlord
            profile = Profile.objects.select_related('user').get(user=user)
            if not profile_complete(profile):
                return redirect('account-profile-update')
            
            # 房东专属逻辑
            landlord_properties = Property.objects.filter(landlord=landlord)
            if not landlord_properties.exists():
                return redirect('add-property')
            elif Message.objects.filter(property__landlord=landlord, status=False).exists():
                return redirect('inbox')
            else:
                return redirect('property-listing')
        except (Landlord.DoesNotExist, Profile.DoesNotExist):
            pass
        
        # 检查是否为经纪人
        try:
            agent = user.agent
            profile = Profile.objects.select_related('user').get(user=user)
            if not profile_complete(profile):
                return redirect('account-profile-update')
            
            # 经纪人专属逻辑
            agent_properties = Property.objects.filter(agent=agent)
            if not agent_properties.exists():
                return redirect('add-property')
            elif Message.objects.filter(property__agent=agent, status=False).exists():
                return redirect('inbox')
            else:
                return redirect('property-listing')
        except (Agent.DoesNotExist, Profile.DoesNotExist):
            pass
        
        # 检查是否为潜在租户
        try:
            prospect = user.prospect_profile
            profile = Profile.objects.get(user=user)
            if not profile_complete(profile):
                return redirect('account-profile-update')
            
            # 潜在租户专属逻辑
            if Message.objects.filter(recipient=user, status=False).exists():
                return redirect('inbox')
            else:
                return redirect('listings')
        except (Prospect.DoesNotExist, Profile.DoesNotExist):
            pass
        
        # 可选:如果用户没有对应类型实例,可添加默认处理,比如提示完善资料
        # return redirect('account-profile-update')
    
    # 未登录或无对应类型的用户重定向登录
    request.session['user_type'] = 'default'
    return redirect('account-login')

额外优化建议

  • 将profile_complete函数移到视图外,避免每次请求重复定义。
  • 为Profile模型添加OneToOneField关联User,简化查询逻辑。
  • 可考虑使用Django的AbstractUser扩展用户模型,统一管理用户类型,减少关联查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 01:17:55