使用自定义QuerySet作为Manager向所有查询集添加注释

Sha*_*ane 6 django django-models

我不确定如何在这个词上精确地写一些字,但是我想做的是为模型使用自定义QuerySet,但是我想注释任何queryset的结果。因此,无论是应用过滤器,还是直接获取对象(我认为最后仍然是filter()调用),我都希望应用注释,以便可以在返回的Model对象中访问它们。

我当前的解决方案是使用自定义QuerySet +自定义管理器,并且自定义管理器将自定义调用传递给自定义Queryset上的相应调用。当然,不幸的是,对于我想要的任何自定义方法,都需要在管理器和查询集之间匹配方法。

我知道CustomQuerySet.as_manager()可以避免这种重复,但是如果使用它,那么我将失去覆盖get_queryset()的能力,因此我的注释可以应用于评估查询集的所有情况。

有没有更清洁的方法可以执行此操作,因此在最终评估查询集时,我仍然可以链接调用并应用我的注释?

理想情况下,我想继续使用标准呼叫,例如: Model.objects.most_liked().near()Model.objects.get(id=model_id)

而不是让做类似的东西添加add_annotations()方法来我的自定义查询集,从而需要始终调用该方法,每当我想模型对象(即我不想Model.objects.get(id=id).add_annotations()Model.objects.near().add_annotations()等)

但不必在manager和queryset之间重复这些方法?理想情况下,无需侵入私有方法或类似方法。我曾短暂地__iter__尝试重写CustomQuerySet类以添加注释,但是这样做似乎不合适。

下面是模型,查询集和管理器的样本设置。这些当然不是我的真实班级名字,只是问题的填充物。希望我已经包括了足够多的内容来使我的问题易于理解:)

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()
Run Code Online (Sandbox Code Playgroud)

Gre*_*reg 6

您应该使用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()
Run Code Online (Sandbox Code Playgroud)