使用 Django 和 django-guardian 对象权限的每个对象的组

Posted

技术标签:

【中文标题】使用 Django 和 django-guardian 对象权限的每个对象的组【英文标题】:Groups per object using Django and django-guardian object permissions 【发布时间】:2014-06-21 00:31:39 【问题描述】:

我目前正在创建一个结构,其中有属于公司的员工。 在这家公司内,我需要能够创建多个组。如果你愿意,排名。您可以将较少的权限分配给较低的等级,而将更多的权限分配给较高的等级。

我想获得对象级别的权限,我注意到 django-guardian 项目正好给了我我需要的东西。它适用于本机用户和组对象,因此我现在正试图找到一种在公司对象中实现本机组对象的方法。

我面临的问题是组中的名称是唯一的。所以如果两个公司加同一个组,就会出现错误。

我找到了一个在某种程度上可行但对我来说似乎很“hacky”的实现。在我的公司中,我声明了一个引用 Group 的组变量:

class Company(models.Model):
    ...
    groups = models.ManyToManyField(Group, through='CompanyRole')

CompanyRole 基本上包含组名以及对公司和组的引用

class CompanyRole(models.Model):
    group = models.ForeignKey(Group)
    company = models.ForeignKey(Company)
    real_name = models.CharField(max_length=60, verbose_name=_('Real name'))

    objects = CompanyGroupManager()

我用一种方便的方法创建了一个自定义管理器来添加一个新的“公司组”

class CompanyGroupManager(models.Manager):
    def create_group(self, company, group_name):
        un_group_name = str(company.id) + '#' + group_name
        group = Group.objects.create(name=un_group_name)
        company_group = self.model(
            real_name=group_name, 
            company=company, 
            group=group
        )

        company_group.save(using=self._db)
        return company_group

这是我不太满意的部分。为了改变 Group 模型上唯一名称的问题,我使用了公司 ID、井号和实际组名的组合以避免冲突。

现在我的问题是:在我的场景中是否有更好的方法,我是否遗漏了什么或者这是完成我需要的好方法?

【问题讨论】:

您可以在公司模型中使用硬连线的自定义权限而不是组吗? 基本上我想做的就是。在公司中,您应该能够创建可以授予全局权限和对象权限的部门。假设您有一个名为初级程序员的部门,我希望能够授予他们对某些项目的完全权限,但在全局范围内对他们创建的其他项目授予很少的权限。现在这是可能的,但我的解决方案似乎相当老套。硬连线自定义权限是什么意思? 嗨 Jeffrey,我的意思是使用 permissions 元属性来定义您自己的权限,您可以检查这些权限。您提到了您发布的代码、项目和部门中不存在的其他几个模型,所以我对您的模型结构有点不清楚。但是,我想我看到了你想要完成的事情。我将使用我过去使用的设置添加答案。您能否提供一个示例列表,列出您希望为用户提供的权限/角色? 【参考方案1】:

不幸的是,没有办法绕过这个独特的要求,因为这个字段被用作 id: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.unique

您的选择如下:

1) 模拟模型。

您基本上只是创建一个没有独特要求的新组模型。这里的缺点是你需要在任何地方使用它,所以如果这需要更新 3rd 方应用程序,它可能不值得。

2) 让你的名字独一无二。 (和你一样)

确保您妥善记录您的约定,以便所有未来的编码人员都知道他们在看什么。像“公司名称”#“组名称”这样的东西可能比 id 更直观。如果哈希可能出现在任何一个中,则使用更确定的分隔符(“__”是 django 中连接相关概念的一种相对常见的方式,我可能会这样做)。

我建议您添加以下内容以方便您访问该名称。

def get_name(self):
    # Explain how you get the group name from your uniqueified name
    return self.name.split('#')[1] 

Group.add_to_class('get_name', get_name)

当您在应用中访问群组名称时,只需执行以下操作:

my_group.get_name()

您可能还希望将生成唯一名称放入 save() 的覆盖版本中。这将使您在模型和视图之间更好地分开......

【讨论】:

这正是我最终所做的。 :) 但是,我发现这种方法的缺点如下:例如,您有一个模型:MyModel。具有权限:view_mymodel、change_mymodel、add_mymodel、delete_mymodel。要查看、更改和删除权限,请将它们添加到对象并检查权限 (user.has_perm('view_mymodel', obj))。但是对于添加,您不能也将使用 user.has_perm('add_mymodel')。如果一个组织的用户属于具有添加权限的组,而另一个组织的用户属于没有权限的组怎么办?

以上是关于使用 Django 和 django-guardian 对象权限的每个对象的组的主要内容,如果未能解决你的问题,请参考以下文章

使用 Django 模板和标签而不使用 Django 的其余部分

django-redis-cache 和 django-redis 用于使用 Django 进行 redis 缓存的区别?

使用 Python 和 Django 搭建 Web 应用

django2.0和3.0的区别

使用 django-allauth 和 django-rest 框架

如何在 Django 中使用 Javascript 和经过身份验证的用户调用 Django API