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')
问题排查与修复
核心问题分析
- 用户验证逻辑无效:
if user:永远为真——即使未登录,request.user也是匿名用户对象,导致后续逻辑执行出错后直接走到重定向登录的代码。正确判断应为if user.is_authenticated:。 - 用户类型判断逻辑错误:
Landlord.user == user是拿模型类的字段和用户对象比较,完全不成立,应该用hasattr(user, 'landlord')或try-except判断用户是否关联了对应实例。user.landlord == 'landlord'是拿Landlord实例和字符串比较,逻辑错误,无需此判断,确认用户是房东后直接执行对应逻辑即可。
- 异常处理后无后续动作:try块抛出异常(比如用户没有对应Profile)后,
pass之后没有任何处理,直接走到最后重定向登录。 - 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
相关产品推荐
相关产品推荐

