【发布时间】:2011-09-17 01:14:54
【问题描述】:
我的模型上有一个 private 布尔标志,以及一个使用过滤器覆盖 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()
我希望将排除私有模型的默认查询集作为默认安全措施,防止意外使用显示私有模型的模型。
不过,有时我会想展示私人模型,所以我在管理器上有以下内容:
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
这非常有效,但我无法链接过滤器。当我有一个指向 myModel 并使用 otherModel.mymodel_set 的 fk 时,这会成为一个问题。 otherModel.mymodel_set.for_user(user) 不起作用,因为 mymodel_set 返回一个 QuerySet 对象,而不是管理器。
现在真正的问题开始了,因为我看不到让 for_user() 方法在 QuerySet 子类上工作的方法,因为我无法从 QuerySet 访问完整的、未过滤的查询集(基本上覆盖 get_query_set)子类,就像我可以在管理器中一样(使用 super() 获取基本查询集。)
解决此问题的最佳方法是什么?
我没有绑定到任何特定的界面,但我希望它尽可能的 djangoy/DRY。显然,我可以放弃安全性,只在每次调用时调用一个方法来过滤掉私人任务,但我真的不想这样做。
更新
manji 下面的答案非常接近,但是当我想要的查询集不是默认查询集的子集时它会失败。我想这里真正的问题是如何从链式查询中删除特定过滤器?
【问题讨论】:
标签: django django-models orm django-queryset