Django使用Model检查用户类型的最佳实践

eoxn13cs  于 2023-06-25  发布在  Go
关注(0)|答案(2)|浏览(101)

我正在做一个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')
9jyewag0

9jyewag01#

我能够使用hasattr函数来检查登录用户是否与房东,代理或前景对象相关。我意识到我在用字符串做用户类型比较。

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 hasattr(user, 'landlord') or hasattr(user, 'agent'):
        try:
            profile = Profile.objects.select_related('user').get(user=user)
            if not profile_complete(profile):
                return redirect('account-profile-update')
            elif hasattr(user, '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 hasattr(user, 'prospect_profile'):
        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')
h7appiyu

h7appiyu2#

好吧,这不是对你的问题的直接答案,但是,这是一种更好地组织代码的方法,通过这样做,也许可以让你更好地理解代码,自己找到答案并学习。
首先,使用Django shell来了解你正在处理的对象的类型。
python manage.py shell(如果你在python环境中安装了类似ipython的东西会更好。
如果您这样做:

import Landlord

Landlord.user

您将看到这与<django.db.models.fields.related_descriptors...类似,因此您没有比较用户的类型。
其次,如果你看你的模型。您可以看到大多数与用户相关的模型共享相同的代码。这里是您可以使用抽象模型的地方https://docs.djangoproject.com/en/4.2/topics/db/models/#abstract-base-classes
类似于:

AGENT = "agent"
LANDLORD = "landlord"
PROSPECT = "prospect"
TYPE_CHOICES = (
    (AGENT, "Agent"),
    (LANDLORD, "Landlord"),
    (PROSPECT, "Prospect"),
)

class BaseUser(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    is_verified = models.BooleanField(default=False)
    user_type = models.CharField(max_length=20, choices=TYPE_CHOICES, default=AGENT)

    class Meta:
        abstract = True

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

class Landlord(BaseUser):
    # custom code for landlord
    pass

class Agent(BaseUser):
    # custom code for agent
    pass

class Prospect(BaseUser):
    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 become_tenant(self, property):
        # code ...
        pass

然后,您只需根据需要检查此user_type属性即可。

from my.models import AGENT, LANDLORD, PROSPECT

# code ...

if request.user.user_type == AGENT:
    # logged in user is an agent
    pass

此外,考虑将检查是否有未读消息的代码作为BaseUser类中的一个方法移动到BaseUser类中。然后,您可以简单地对视图执行user.has_unread_messages(),并保持其干净,将逻辑和DB检查留在模型文件中。

相关问题