使用自定义QuerySet作为Manager向所有查询集添加注释 [英] Adding annotations to all querysets with a custom QuerySet as Manager

查看:67
本文介绍了使用自定义QuerySet作为Manager向所有查询集添加注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm not sure how to put words on this precisely, but what I'm trying to do is use a custom QuerySet for a model, but I want to annotate the results of any queryset. So whether filters were applied, or it was a direct get of an object (which I think is still a filter() call in the end), I want the annotations to be applied so I can access them in the Model objects I get back.

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

My current solution is using a custom QuerySet + custom Manager, and the custom Manager passes custom calls off to the appropriate call on the custom Queryset. Of course, this has the unfortunate need to match methods between the manager and queryset for any custom method I want.

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

I know that CustomQuerySet.as_manager() exists to avoid this duplication, but if I use that, then I lose the ability to override get_queryset() so my annotations can be applied in all cases of evaluating a queryset.

有没有更清洁的方法可以做到这一点,所以我仍然可以链接呼叫,并且在最终评估查询集时可以应用我的注释?

Is there a cleaner way to do this so I am still left with the ability to chain calls and have my annotations apply when the queryset is finally evaluated?

理想情况下,我想继续使用标准调用,例如:
Model.objects.most_liked()。near()

Model.objects.get(id = model_id)

Ideally I'd like to keep using standard calls like: Model.objects.most_liked().near() and Model.objects.get(id=model_id)

例如将add_annotations()方法添加到自定义QuerySet中,从而需要在我得到模型对象时随时调用该方法(即,我不想 Model.objects.get(id = id).add_annotations () Model.objects.near()。add_annotations()等)

As opposed to having to do something like add an add_annotations() method to my custom QuerySet, thereby needing to always call that method anytime I get Model objects (ie. I don't want Model.objects.get(id=id).add_annotations() and Model.objects.near().add_annotations() and so on)

,但不必在manager和查询集?理想情况下,无需侵入私有方法或类似方法。我短暂地在CustomQuerySet类上重写了 __ iter __ 来添加注释,但是这样做似乎不合适。

but not have to repeat the methods between manager and queryset? Ideally without hacking into private methods or anything like that. I briefly toyed with overriding __iter__ on the CustomQuerySet class to add the annotations then, but it didn't seem right to do that.

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

Sample setup of model, queryset, and manager below. These of course aren't my real class names, just fillers for the question. Hopefully I've included enough to make my question understandable :)

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类,您可以在将其应用于模型之前进一步对其进行自定义。例如:

You should use the from_queryset method - it allows you to create a Manager class which you can further customise before applying to your model. For example:

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()

这篇关于使用自定义QuerySet作为Manager向所有查询集添加注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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