gpt4 book ai didi

django - “私有(private)”模型、默认查询集和链接方法

转载 作者:行者123 更新时间:2023-12-02 02:24:59 24 4
gpt4 key购买 nike

我的模型上有一个 private bool 标志,还有一个覆盖 get_query_set 方法的自定义管理器,带有过滤器,删除了 private=True:

class myManager(models.Manager):
def get_query_set(self):
qs = super(myManager, self).get_query_set()
qs = qs.filter(private=False)
return qs

class myModel(models.Model):
private = models.BooleanField(default=False)
owner = models.ForeignKey('Profile', related_name="owned")
#...etc...

objects = myManager()

我希望将默认查询集排除私有(private)模型作为一种安全措施,以防止意外使用显示私有(private)模型的模型。

然而,有时我会想展示私有(private)模特,所以我在经理上有以下内容:

def for_user(self, user):
if user and not user.is_authenticated():
return self.get_query_set()
qs = super(myManager, self).get_query_set()
qs = qs.filter(Q(owner=user, private=True) | Q(private=False))
return qs

这非常有效,但我无法链接过滤器。当我有一个 fk 指向 myModel 并使用 otherModel.mymodel_set 时,这就成了一个问题。 otherModel.mymodel_set.for_user(user) 不会工作,因为 mymodel_set 返回一个 QuerySet 对象,而不是管理器。

现在真正的问题开始了,因为我看不到使 for_user() 方法在 QuerySet 子类上工作的方法,因为我无法从 QuerySet 访问完整的、未过滤的查询集(基本上覆盖 get_query_set)子类,就像我在管理器中所做的那样(使用 super() 获取基本查询集。)

解决此问题的最佳方法是什么?

我不依赖于任何特定的界面,但我希望它尽可能地成为 djangoy/DRY。显然,我可以放弃安全性,只调用一种方法来过滤掉每次调用的私有(private)任务,但我真的不想这样做。

更新

manji 在下面的回答非常接近,但是当我想要的查询集不是默认查询集的子集时它会失败。我想这里真正的问题是如何从链式查询中删除特定过滤器?

最佳答案

定义一个自定义查询集(包含您的自定义过滤器方法):

class MyQuerySet(models.query.QuerySet):

def public(self):
return self.filter(private=False)

def for_user(self, user):
if user and not user.is_authenticated():
return self.public()
return self.filter(Q(owner=user, private=True) | Q(private=False))

定义一个将使用 MyQuerySet 的自定义管理器(MyQuerySet 自定义过滤器将可以访问,就好像它们是在管理器中定义的一样[通过覆盖 __getattr__]):

# A Custom Manager accepting custom QuerySet
class MyManager(models.Manager):

use_for_related_fields = True

def __init__(self, qs_class=models.query.QuerySet):
self.queryset_class = qs_class
super(QuerySetManager, self).__init__()

def get_query_set(self):
return self.queryset_class(self.model).public()

def __getattr__(self, attr, *args):
try:
return getattr(self.__class__, attr, *args)
except AttributeError:
return getattr(self.get_query_set(), attr, *args)

然后在模型中:

class MyModel(models.Model):
private = models.BooleanField(default=False)
owner = models.ForeignKey('Profile', related_name="owned")
#...etc...

objects = myManager(MyQuerySet)

现在您可以:

¤ 默认情况下仅访问公共(public)模型:

    MyModel.objects.filter(..

¤ 访问 for_user 模型:

    MyModel.objects.for_user(user1).filter(..

由于 ( use_for_related_fields = True ),同一经理将用于相关经理。所以你也可以:

¤ 默认情况下只能访问来自相关经理的公共(public)模型:

    otherModel.mymodel_set.filter(..

¤ 从相关经理处访问 for_user:

    otherModel.mymodel_set.for_user(user).filter(..


更多信息:Subclassing Django QuerySets & Custom managers with chainable filters (django 片段)

关于django - “私有(private)”模型、默认查询集和链接方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6383860/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com