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

ert*_*tan 5 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
Run Code Online (Sandbox Code Playgroud)

我希望能够使用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')
Run Code Online (Sandbox Code Playgroud)

这给了我一个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'))
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

编辑:

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

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

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

Som*_*Foo 2

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

另一种可行的方法是查看自定义管理器。您可以为每个模型客户编写一个自定义管理器并相应地查询它。但这一切都会导致应用程序变得复杂,并且很快就会失控。应用程序安全层中的任何错误对您来说都是一场噩梦。

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