在Django中参数化筛选管理器查询集

在Django中参数化筛选管理器查询集,django,django-queryset,django-managers,Django,Django Queryset,Django Managers,我想在Django中为我的模型实现某种行级安全性。我想根据一些要求尽可能低地过滤掉数据 现在,我知道我可以像上面所说的那样为这个模型创建指定的管理器,但对我来说,它似乎需要是静态的。我也知道,我可以创建一个方法,返回我想要的queryset,但这是不够的,我的意思是,获取所有数据的可能性仍然存在,最简单的错误可能会导致数据泄漏 所以我找到了这篇文章,但正如作者所说的——和全球国家混在一起既不安全也不漂亮。这篇文章已经有将近10年的历史了,所以我希望有人能想出一个更好的通用解决方案 下面是一个示例

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

现在,我知道我可以像上面所说的那样为这个模型创建指定的管理器,但对我来说,它似乎需要是静态的。我也知道,我可以创建一个方法,返回我想要的queryset,但这是不够的,我的意思是,获取所有数据的可能性仍然存在,最简单的错误可能会导致数据泄漏

所以我找到了这篇文章,但正如作者所说的——和全球国家混在一起既不安全也不漂亮。这篇文章已经有将近10年的历史了,所以我希望有人能想出一个更好的通用解决方案

下面是一个示例,可以直观地了解我需要什么:

models.py:

class A(models.Model): 
    ...

class B(models.Model): 
    user = models.ForeignKey(User) 
    a = models.ForeignKey(A)
我想创建全局功能,仅当B的实例以
user
作为登录用户存在时,才能获取
A
的对象

我想出了一个解决方案,只需覆盖
A
管理器的
get\u queryset()
,如下所示:

经理.py

class AManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset(b__user=**and_here_i_need_a_user**)
但我找不到合适的参数

==编辑====


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

所以你的思路是对的。像这样的怎么样

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')

所以你的思路是对的。像这样的怎么样

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')

这不是一件你可以或者不应该做的事情。有很多情况下没有“登录用户”。当然,但使用通用解决方案,我可以非常轻松地处理该异常。但这就是我的观点。根本没有通用的解决方案。经理对请求一无所知,这是一个基本的分离问题。好吧,还有其他方法来实现吗?我的意思是,rls的应用相当广泛,应该有可能在低于中间件的级别上实现这一点。这不是一件你可以或者应该想做的事情。有很多情况下没有“登录用户”。当然,但使用通用解决方案,我可以非常轻松地处理该异常。但这就是我的观点。根本没有通用的解决方案。经理对请求一无所知,这是一个基本的分离问题。好吧,还有其他方法来实现吗?我的意思是rls应用非常广泛,应该有可能在比中间件更低的级别上实现这一点