Django中多个模型的原始查询和行级访问控制

时间:2017-11-21 22:52:45

标签: python django postgresql django-guardian

我正在尝试为用户提供一个接口,以便在数据库上编写自定义查询。我需要确保他们只能查询他们被允许的记录。为此,我决定使用django-guardian应用基于行的访问控制。

以下是我的模式的样子

class BaseClass(models.Model):
    somefield = models.TextField()
    class Meta:
        permissions = (
            ('view_record', 'View record'),
        )

class ClassA(BaseClass):
    # some other fields here
    classb = models.ForeignKey(ClassB)

class ClassB(BaseClass):
    # some fields here
    classc = models.ForeignKey(ClassC)

class ClassC(BaseClass):
    # some fields here

我希望能够使用get_objects_for_group,如下所示:

>>> group = Group.objects.create('some group')
>>> class_c = ClassC.objects.create('ClassC')
>>> class_b = ClassB.objects.create('ClassB', classc=class_c)
>>> class_a = ClassA.objects.create('ClassA', classb=class_b)
>>> assign_perm('view_record', group, class_c)
>>> assign_perm('view_record', group, class_b)
>>> assign_perm('view_record', group, class_a)
>>> get_objects_for_group(group, 'view_record')

这给了我一个QuerySet。我可以使用上面定义的BaseClass并在其他相关类上编写原始查询吗?

>>> qs.intersection(get_objects_for_group(group, 'view_record'), \
                    BaseClass.objects.raw('select * from table_a a'
                                          'join table_b b on a.id=b.table_a_id '
                                          'join table_c c on b.id=c.table_b_id '
                                          'where some conditions here'))

这种方法有意义吗?有没有更好的方法来解决这个问题?

谢谢!

修改

解决问题的另一种方法可能是为每个用户创建一个单独的表。我理解这可能会增加我的应用程序的复杂性,但是:

  • 长时间内用户数不会超过100。不是消费者应用程序。
  • 根据我们的用例,我不太可能需要查询这些表。我不会编写一个需要聚合table1,table2,table3中属于同一模型的任何内容的查询。
  • 为每位客户维护一张单独的表可能会有优势。

你认为这是一种可行的方法吗?

3 个答案:

答案 0 :(得分:3)

在研究了很多选项之后,我发现我可以在PostgreSQL上使用Row Level Security在数据库级解决这个问题。它最终是最简单和最优雅的。

This article帮助我将应用程序级用户与PostgreSQL策略联系起来。

通过我的研究我学到的是:

  • 将来,当客户可能会影响彼此时,单独的表仍然是一个选项。查询性能,因为它们可以运行任意查询。

  • 如果您计划使用原始或临时查询,尝试在ORM级别解决它几乎是不可能的。

答案 1 :(得分:2)

我想你已经知道你需要做什么了。你正在寻找的是多租户。虽然每个客户不是一张桌子。最适合您的是每个客户一个架构。不幸的是,关于多租户的最好的文章已经没有了。看看你是否能找到一个缓存版本:https://msdn.microsoft.com/en-us/library/aa479086.aspx否则互联网上会有很多文章可供使用。

另一种可行的方法是查看custom managers。您可以为每个Model-Customer编写一个自定义管理器并相应地进行查询。但所有这些都将导致应用程序的复杂性,很快就会失控。应用程序安全层中的任何错误都是您的噩梦。

权衡两者我倾向于说你在编辑中所说的多租户解决方案是迄今为止最好的方法。

答案 2 :(得分:-1)

首先,您应该向我们提供更多详细信息,您的架构如何设置和构建,使用django以便我们为您提供帮助。你有没有实现API?如果你正在构建一个大规模的应用程序,消耗大量的数据,那么使用django模板并不是一个好主意。因为这会大量影响查询加载。我可以建议从后端提取你的前端。