【问题标题】:Check which model is the current user an instance of in Django检查哪个模型是当前用户在 Django 中的一个实例
【发布时间】:2020-12-25 11:45:12
【问题描述】:

我的 Django 项目中的 Employee 模型与内置的 Django User 模型具有 OneToOneField 关系。然后,我进一步将此 Employee 模型继承为两个不同的 Manager 和 Associate 模型。 现在,当用户登录时,我想在我的 HTML 模板中检查该用户是经理还是助理,以便我可以显示不同的选项,具体取决于他们是经理还是助理。最好的方法是什么?

Models.py-

GENDER = [('male','Male'),('female','Female')]

class Employee(models.Model):
    user_def = models.OneToOneField(User,on_delete=models.CASCADE,null=True)
    name = models.CharField(max_length = 50)
    age = models.IntegerField()
    gender = models.CharField(max_length = 10,choices = GENDER)

    def __str__(self):
        return self.name

class Manager(Employee):
    dept = models.CharField(max_length = 50)

    def __str__(self):
        return super().__str__()

class Associate(Employee):
    reports_to = models.ForeignKey(Manager,on_delete=models.CASCADE)

    def __str__(self):
        return super().__str__()

【问题讨论】:

    标签: python django django-models django-views django-templates


    【解决方案1】:

    哦,使用模型继承是吗? Django有three types of model inheritance,根据你的问题,你需要的是Meta inheritance

    在这种情况下,您希望使您的 Employee 抽象并在 user_def 字段中,定义提供从用户到子类模型的向后关系的 related_name,在您的情况下是 @ 987654327@ 或 Associate 型号。 You can't use any related_name however。您需要在相关名称中包含应用标签和类,例如:related_name="%(app_label)s_%(class)s"。在这里,app_labelclass 将是应用程序标签和 ManagerAssociate 的类,因此如果您在名为 hr 的应用程序中定义模型,则从 user 获取向后关系( user 是用户实例)到经理,你使用user.hr_manager。同样,如果用户是关联用户,请使用user.hr_associate

    因此,这种向后关系基本上回答了您的问题,因为由于用户与您的 Employee 模型具有一对一的关系,因此用户只能是经理或助理。它们是相互排斥的。因此,如果您的用户是经理,那么如果您请求 user.hr_manager,该用户将返回一个 Manager 实例,如果您请求 user.hr_associate,该用户将返回 None。

    现在我注意到您已在 OneToOneField 上允许 null=True,因此用户可能会为 user.hr_manageruser.hr_associate 的两个实例返回 None。因此,请记住对用户进行彻底的 if/elif/else 检查。

    GENDER = [('male','Male'),('female','Female')]
    
    class Employee(models.Model):
        user_def = models.OneToOneField(
            User,
            on_delete=models.CASCADE,
            null=True,
            related_name="%(app_label)s_%(class)s"
        )
        name = models.CharField(max_length=50)
        age = models.IntegerField()
        gender = models.CharField(
            max_length=10,
            choices = GENDER
        )
    
        class Meta:
            abstract = True
    
    class Manager(Employee):
        dept = models.CharField(max_length=50)
    
        def __str__(self):
            return self.name
    
    class Associate(Employee):
        reports_to = models.ForeignKey(
            Manager,
            on_delete=models.CASCADE
        )
    
        def __str__(self):
            return self.name
    

    编辑: 我还没有测试过代码,特别是关于user.hr_manager/user.hr_associate的部分。如果没有反向关系,它们实际上可能会抛出错误而不是 None 。在这种情况下,您可以简单地捕获并忽略错误,然后继续进行下一个 if/elif/else 检查。

    【讨论】:

    • 很好的答案,除了我不喜欢您对相关名称的命名约定。将属性命名为 is_hr_manager 意味着该属性返回 true 或 false。在这种情况下,它返回相关对象。所以hr_manager 更适合 IMO。
    • @EduardLuca 这是一个有效的观点。我不知道是什么让我这么命名的——可能是问题的上下文。我将编辑我的答案,以便名称反映返回值。感谢收看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-01
    • 2017-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多