什么时候应该使用自定义管理器而不是Django中的自定义QuerySet?

Joh*_*ann 47 python django orm django-managers

在Django中,自定义管理器是组织可重用查询逻辑的好方法.该文件指出,有可能是您想自定义管理两方面的原因:添加额外的管理方法,和/或修改初始查询集经理的回报.

但是,它继续描述了如何创建自定义QuerySet,以及可以通过数据模型直接从数据模型访问这些查询集QuerySet.as_manager().QuerySet.as_manager()创建的Manager实例与前一个示例中的PersonManager几乎完全相同.

在自定义Manager和/或自定义QuerySet之间如何组织逻辑似乎有很大的灵活性.有人可以解释我应该决定何时使用其中一种的原则吗?

Tim*_*ony 31

主要是为了便于查询的组合.通常,如果您希望能够在查询集调用链中对现有查询集执行某些操作,则可以使用QuerySet.

例如,假设你有一个Image,有一个模型width,height领域:

class Image(models.Model):
    width = ...  # Width in pixels
    height = ... # Height in pixels
Run Code Online (Sandbox Code Playgroud)

你可以写一些自定义QuerySet方法:

class ImageQuerySet(models.QuerySet): 
    def landscapes(self):
        return self.filter(width__gte=models.F('height'))

    def portraits(self):
        return self.filter(width__lte=models.F('height'))

    def small(self):
        return self.filter(width__lte=1200)

    def large(self):
        return self.filter(width__gte=1200)

class ImageManager(models.Manager):
    def get_queryset(self):
        return ImageQuerySet(self.model, using=self._db)
Run Code Online (Sandbox Code Playgroud)

现在您可以轻松创建动态查询集:

Image.objects.all().portraits().small()
Image.objects.all().large().portraits()
Run Code Online (Sandbox Code Playgroud)

从逻辑上讲,这些函数应主要关注查询集模型的现有查询集的分区或重新定义.对于不在现有查询集上运行的情况,您根本不想返回查询集,或者您可能必须执行一些不涉及此特定模型的相关逻辑,而不是更适合的模型管理器.

  • 从Django 1.7开始,您可以将`objects`设置为`YourCustomQuerySet.as_manager()`.然后,您只需要创建查询集类.请参阅https://docs.djangoproject.com/en/dev/topics/db/managers/#creating-a-manager-with-queryset-methods (9认同)

meh*_*met 10

我一直在反复学习自己是什么Managervs. QuerySetso,我以为我最好在这里写,所以下次我想变得更容易。

A Manager是附加到模型的类,并返回一个QuerySet实例, objects它是默认的管理器。大多数经理方法,例如。all()filter()返回queryset实例。

更详细地说,当YourModel.objects.filter(..)您获得查询集实例时。当您想再次过滤它时,您只能链接另一个.filter(..)方法,因为它也可以在QuerySet类中使用。那就是您想要的..在管理器和它返回的查询集上都有您的方法。

如果filter还不是管理器方法,则YourModel.objects.all()必须获取查询集,然后filter从那里添加方法。

为使事情变得容易,Django as_manager()在QuerySet类上定义了一个方法,该方法将其转换为经理[docs]。因此,您可以在查询集上定义所有自定义方法,并将其转变为管理器,然后附加到模型,这样您就可以首次调用它(作为管理器方法)并根据需要进行多次链接(根据需要) queryset方法)。

在写这个答案时,我想知道Django附带的管理器方法不是queryset方法,我想到的第一个get_or_create方法是方法,因为它似乎不需要queryset。但猜猜怎么了?事实证明,这也是在QuerySet课堂上定义的。

简而言之,您几乎总是想编写QuerySet方法,并通过来将它们也放在管理器中as_manager()