在Django中,自定义管理器是组织可重用查询逻辑的好方法。 docs状态有两个原因可能需要自定义Manager:添加额外的Manager方法,和/或修改Manager返回的初始QuerySet。
但是,it goes on to describe如何创建自定义QuerySet,并且可以通过QuerySet.as_manager()
直接从数据模型作为管理员访问这些查询集。 QuerySet.as_manager()创建的Manager实例与前一个示例中的PersonManager几乎完全相同。
似乎在如何在自定义Manager和/或自定义QuerySet之间组织逻辑方面有很大的灵活性。有人可以解释我应该决定何时使用其中一种的原则吗?
答案 0 :(得分:24)
主要是为了便于查询的组合。通常,如果您希望能够在查询集调用链中对现有查询集执行某些操作,则可以使用QuerySet
。
例如,假设您的Image
模型具有width
,height
字段:
class Image(models.Model):
width = ... # Width in pixels
height = ... # Height in pixels
您可以编写一些自定义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)
现在您可以轻松创建动态查询集:
Image.objects.all().portraits().small()
Image.objects.all().large().portraits()
逻辑上,这些函数应主要关注查询集模型的现有查询集的分区或重新定义。对于您不在现有查询集上运行的情况,您根本不想返回查询集,或者您可能必须执行一些不涉及此特定模型的相关逻辑,而不是模特经理更适合。
答案 1 :(得分:5)
我不断地自我介绍Manager
与QuerySet
是什么,所以,我认为我最好在这里写,这样下次我想知道就更容易了。
Manager
是附加到模型的类,并返回QuerySet
实例,objects
是默认管理器。大多数经理方法,例如。 all()
,filter()
返回查询集实例。
更详细地讲,当您执行YourModel.objects.filter(..)
时,将获得一个queryset实例。当您想再次对其进行过滤时,可以链接另一个.filter(..)
方法,因为它也可以在QuerySet
类中使用。那就是您想要的..在管理器和它返回的查询集上都有您的方法。
如果filter
也不是管理器方法,则必须执行YourModel.objects.all()
来获取查询集,然后然后添加filter
方法) 从那里。
为使事情变得容易,Django在QuerySet类上定义了一个as_manager()
方法,这使它变成了一个管理器[docs]。因此,您可以在查询集上定义所有自定义方法,并将其转变为管理器,然后附加到模型,这样您就可以第一次调用它(作为管理器方法)并根据需要进行多次链接(根据需要) queryset方法)。
写下这个答案,我想知道Django附带的管理器方法不是queryset方法,我想到的第一个方法是get_or_create
方法,因为它似乎不需要查询集。但猜猜怎么了?事实证明,它也是在QuerySet
类上定义的。
长话短说,您几乎总是想编写QuerySet方法并通过as_manager()
将它们也放在管理器中。