Django

时间:2019-02-20 16:50:31

标签: django django-queryset django-managers

我想在Django中为我的模型实现某种行级安全性。我想根据某些要求过滤掉尽可能低的数据。

现在,我知道我可以像docs所说的那样为该模型创建指定的管理器,但是对我来说,它需要是静态的。我也知道我可以创建只需要返回查询集的方法,但是这还不够,我的意思是仅获取所有数据的可能性仍然存在,最简单的错误可能导致它们泄漏。

因此,我发现了this个帖子,但正如作者所说-与全球性国家混为一谈既不安全也不很漂亮。这篇文章已有将近10年的历史,所以我希望也许有人提出了更好的通用解决方案。

以下是一个示例,可以直观显示我的需求:

models.py:

class A(models.Model): 
    ...

class B(models.Model): 
    user = models.ForeignKey(User) 
    a = models.ForeignKey(A)

并且我想创建全局功能,以仅当存在具有A作为登录用户的B实例的情况下获取user的对象。

我想出了一种解决方案,可以像这样覆盖get_queryset()经理的A

managers.py

class AManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset(b__user=**and_here_i_need_a_user**)

但是我找不到使它参数化的热力

====编辑====

另一个想法是完全不允许显式地获取A的查询集,而只能通过B的相关字段来获取,但是我找不到任何参考来实现该目的。有人做过类似的事情吗?

1 个答案:

答案 0 :(得分:0)

因此,您处于正确的轨道上。这样的事情怎么样...

class AQuerySet(models.QuerySet):
    def filter_by_user(self, user, *args, **kwargs):
        user_filter = Q(b__user=user)
        return self.filter(user_filter, *args, **kwargs)

class AManager(models.Manager):
    queryset_class = AQuerySet

    def filter_by_user(self, user, *args, **kwargs):
        return self.get_queryset().filter_by_user(user, *args, **kwargs)

class A(models.Model):
    objects = AManager()
    # ...

然后您可以像这样使用它:

A.objects.filter_by_user(get_current_user(), some_filter='some_value')