我想知道是否有可能(如果可以的话,如何)将多个管理器链接在一起以生成受两个管理器影响的查询集。我将解释我正在处理的特定示例:

我有多个抽象模型类,可用于为其他模型提供小的特定功能。这些模型中的两个是DeleteMixin和GlobalMixin。

DeleteMixin的定义如下:

class DeleteMixin(models.Model):
    deleted = models.BooleanField(default=False)
    objects = DeleteManager()

    class Meta:
        abstract = True

    def delete(self):
        self.deleted = True
        self.save()

基本上,它提供了伪删除(已删除标志),而不是实际删除对象。

GlobalMixin的定义如下:
class GlobalMixin(models.Model):
    is_global = models.BooleanField(default=True)

    objects = GlobalManager()

    class Meta:
        abstract = True

它允许将任何对象定义为全局对象或私有(private)对象(例如公共(public)/私有(private)博客文章)。

这两个都有自己的管理器,这些管理器会影响返回的查询集。我的DeleteManager过滤查询集以仅返回已将已删除标志设置为False的结果,而GlobalManager过滤查询集以仅返回被标记为全局的结果。这是两者的声明:
class DeleteManager(models.Manager):
    def get_query_set(self):
        return super(DeleteManager, self).get_query_set().filter(deleted=False)

class GlobalManager(models.Manager):
    def globals(self):
        return self.get_query_set().filter(is_global=1)

所需的功能是使模型扩展这两个抽象模型,并赋予仅返回未删除和全局结果的能力。我在具有4个实例的模型上运行了一个测试用例:一个是全局且未删除的实例,一个是全局且已删除的实例,一个是非全局且未删除的实例,一个是非全局且删除的实例。如果我尝试获得这样的结果集:SomeModel.objects.all(),则会得到实例1和实例3(两个未删除的实例-太好了!)。如果尝试使用SomeModel.objects.globals(),则会收到一个错误消息,即DeleteManager没有全局变量(这是假设我的模型声明是这样的:SomeModel(DeleteMixin,GlobalMixin)。如果我颠倒顺序,我不会)无法收到错误,但不会过滤掉已删除的错误)。如果我更改GlobalMixin以将GlobalManager附加到全局对象而不是对象(所以新命令将是SomeModel.globals.globals()),则将获得实例1和2(两个全局变量),而我的预期结果将是仅获得实例1(全局,未删除)。

我不确定是否有人遇到过类似情况并得出结果。无论是采用我目前的想法进行工作的方法,还是提供我所追求的功能的返工工作,都将受到高度赞赏。我知道这篇文章有些冗长。如果需要更多解释,我将很乐意提供。

编辑:

我已经在下面发布了针对该特定问题的最终解决方案。它基于到Simon的自定义QuerySetManager的链接。

最佳答案

在Django片段上查看以下片段:http://djangosnippets.org/snippets/734/

不必将自定义方法放在管理器中,而是将查询集本身子类化。这非常容易并且完美地工作。我唯一遇到的问题是模型继承,即使它们将继承查询集,也总是必须在模型子类中定义管理器(只是:子类中的“objects = QuerySetManager()”)。一旦使用QuerySetManager,这将更有意义。

10-04 21:56