Django经理链 [英] Django Manager Chaining

查看:130
本文介绍了Django经理链的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有可能(如果是这样,怎么样)将多个管理人员链接在一起,生成一个受到两个管理者影响的查询集。我将解释我正在处理的具体示例:



我有多个抽象模型类,用于为其他模型提供小的特定功能。其中两个模型是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()
/ pre>

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



GlobalMixin定义如下:

  class GlobalMixin(models.Model):
is_global = models.BooleanField default = True)

objects = GlobalManager()

class Meta:
abstract = True

它允许任何对象被定义为全局对象或私有对象(如公共/私人博文)。



这两个都有他们的自己的管理员影响被返回的查询集。我的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)如果我扭转顺序, t得到错误,但它不会过滤出删除的错误)。如果我更改GlobalMixin以将GlobalManager附加到全局而不是对象(所以新的命令将是SomeModel.globals.globals()),我得到实例1和2(两个全局变量),而我的预期结果将只是获取实例1(全球,未删除的)。



我不知道是否有任何人遇到过与此类似的任何情况,并已经取得成果。要么使我的工作在我目前的想法或重新工作,提供我以后的功能,将非常感激。我知道这个帖子已经有点长了。如果需要更多的解释,我很乐意提供。



编辑


$ b $我已经发布了我以前使用的最终解决方案。这是基于Simon定制的QuerySetManager的链接。

解决方案

请参阅Djangosnippets上的这段代码: http://djangosnippets.org/snippets/734/



而不是放您在管理器中的自定义方法,您将子查询查询器本身。这很简单,工作完美。我唯一的问题是模型继承,您始终必须在子类中定义模型子类中的管理器(即:objects = QuerySetManager()),即使它们将继承查询集。一旦您使用QuerySetManager,这将更有意义。


I was wondering if it was possible (and, if so, how) to chain together multiple managers to produce a query set that is affected by both of the individual managers. I'll explain the specific example that I'm working on:

I have multiple abstract model classes that I use to provide small, specific functionality to other models. Two of these models are a DeleteMixin and a GlobalMixin.

The DeleteMixin is defined as such:

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

    class Meta:
        abstract = True

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

Basically it provides a pseudo-delete (the deleted flag) instead of actually deleting the object.

The GlobalMixin is defined as such:

class GlobalMixin(models.Model):
    is_global = models.BooleanField(default=True)

    objects = GlobalManager()

    class Meta:
        abstract = True

It allows any object to be defined as either a global object or a private object (such as a public/private blog post).

Both of these have their own managers that affect the queryset that is returned. My DeleteManager filters the queryset to only return results that have the deleted flag set to False, while the GlobalManager filters the queryset to only return results that are marked as global. Here is the declaration for both:

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)

The desired functionality would be to have a model extend both of these abstract models and grant the ability to only return the results that are both non-deleted and global. I ran a test case on a model with 4 instances: one was global and non-deleted, one was global and deleted, one was non-global and non-deleted, and one was non-global and deleted. If I try to get result sets as such: SomeModel.objects.all(), I get instance 1 and 3 (the two non-deleted ones - great!). If I try SomeModel.objects.globals(), I get an error that DeleteManager doesn't have a globals (this is assuming my model declaration is as such: SomeModel(DeleteMixin, GlobalMixin). If I reverse the order, I don't get the error, but it doesn't filter out the deleted ones). If I change GlobalMixin to attach GlobalManager to globals instead of objects (so the new command would be SomeModel.globals.globals()), I get instances 1 and 2 (the two globals), while my intended result would be to only get instance 1 (the global, non-deleted one).

I wasn't sure if anyone had run into any situation similar to this and had come to a result. Either a way to make it work in my current thinking or a re-work that provides the functionality I'm after would be very much appreciated. I know this post has been a little long-winded. If any more explanation is needed, I would be glad to provide it.

Edit:

I have posted the eventual solution I used to this specific problem below. It is based on the link to Simon's custom QuerySetManager.

解决方案

See this snippet on Djangosnippets: http://djangosnippets.org/snippets/734/

Instead of putting your custom methods in a manager, you subclass the queryset itself. It's very easy and works perfectly. The only issue I've had is with model inheritance, you always have to define the manager in model subclasses (just: "objects = QuerySetManager()" in the subclass), even though they will inherit the queryset. This will make more sense once you are using QuerySetManager.

这篇关于Django经理链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆