我不确定如何在这个词上精确地写一些字,但是我想做的是为模型使用自定义QuerySet,但是我想注释任何queryset的结果。因此,无论是应用过滤器,还是直接获取对象(我认为最后仍然是filter()调用),我都希望应用注释,以便可以在返回的Model对象中访问它们。
我当前的解决方案是使用自定义QuerySet +自定义管理器,并且自定义管理器将自定义调用传递给自定义Queryset上的相应调用。当然,不幸的是,对于我想要的任何自定义方法,都需要在管理器和查询集之间匹配方法。
我知道CustomQuerySet.as_manager()
的存在就是为了避免这种重复,但是如果我使用Model.objects.most_liked().near()
,那么我将失去覆盖get_queryset()的能力,因此我的注释可以应用于评估查询集的所有情况。
有没有更干净的方法可以执行此操作,因此在最终评估查询集时,我仍然可以链接调用并应用我的注释?
理想情况下,我想继续使用标准调用,例如:
Model.objects.get(id=model_id)
和
Model.objects.get(id=id).add_annotations()
与必须在我的自定义QuerySet中添加add_annotations()方法类似,从而需要在我得到Model对象的任何时候始终调用该方法(即,我不需要Model.objects.near().add_annotations()
和__iter__
等)
但不必在manager和queryset之间重复这些方法?理想情况下,无需侵入私有(private)方法或类似方法。我短暂地在CustomQuerySet类上重写了ojit_code以添加注释,但是这样做似乎不合适。
下面的模型,查询集和管理器的示例设置。这些当然不是我的真实类(class)名字,只是问题的填充物。希望我已经包括了足够多的内容,以使我的问题可以理解:)
class CustomQuerySet(models.QuerySet):
def most_liked(self):
return self.filter(...)
def near(self):
return self.filter(...)
class CustomManager(models.Manager):
def get_queryset(self):
return CustomQuerySet(self.model, using=self._db)\
.annotate(...)\
.annotate(...)
def near(self, latitude, longitude, radius, max_results=100):
return self.get_queryset().near()
def most_liked(self):
return self.get_queryset().most_liked()
class Model(models.Model):
objects = CustomManager()
最佳答案
您应该使用 from_queryset
方法-它允许您创建一个Manager类,您可以在应用到模型之前进一步对其进行自定义。例如:
class CustomQuerySet(models.QuerySet):
def most_liked(self):
return self.filter(...)
class CustomManager(models.Manager.from_queryset(CustomQuerySet)):
def get_queryset(self):
return super(CustomManager, self).get_queryset() \
.annotate(...)
class Model(models.Model):
objects = CustomManager()