Django manager queries don't work in a chain of queries. AttributeError: 'QuerySet' object has no attribute <the manager method>

Django manager queries don't work in a chain of queries. AttributeError: 'QuerySet' object has no attribute <the manager method>

问题:我已经为模型实现了一个自定义管理器,其中只有一个名为 get_by_tag 的自定义查询集,如果我这样使用它,它工作正常:

ViewStatistic.objects.get_by_tag('some-tag-name').filter(user=user_id)

但是当我改变查询的顺序时,是这样的:

ViewStatistic.objects.filter(user=user_id).get_by_tag('some-tag-name')

没用!并引发此错误:

AttributeError: 'QuerySet' object has no attribute 'get_by_tag'

我是不是漏掉了什么?!我怎样才能按这样的顺序执行此操作?

P.S:自定义管理器是这样的:

class MyCustomManager(models.Manager):
    def get_by_tag(self, tag_name):
        posts = Post.objects.filter(tags__pk=tag_name)
        return super().get_queryset().filter(post__pk__in=posts)

当你说 ViewStatistic.objects 它 return 是 <django.db.models.manager.Manager>

的宾语

在你的情况下,因为它派生了 class MyCustomManager 具有基础 class models.manager,所以它 return <your_app.models.MyCustomManager> 的对象有get_by_tag功能,可以访问get_by_tag.

对于第二种情况 ViewStatistic.objects.filter return django.db.models.query.QuerySet 对象,当然它没有名为 get_by_tag 的方法,这就是你得到 AttributeError 的原因。

还有一点与queryset相关的是 优化 QuerySet 的结果本身就是一个 QuerySet,因此可以将优化链接在一起。

https://docs.djangoproject.com/en/3.0/topics/db/queries/#chaining-filters

在你的情况下 get_by_tag return QuerySet 你进一步执行了 .filter() 操作,这很好。

django 官方文档link models Manager 相关的可以关注,查询更详细。 https://docs.djangoproject.com/en/3.0/topics/db/queries/

如果您想在查询集链内使用您的查询集方法,而不仅仅是直接在管理器之后,您应该将它们定义为连接到管理器的自定义 QuerySet class 的方法。

Django 文档中描述了两种解决方案 Creating a manager with QuerySet methods.

公共部分 - 带有查询集方法的自定义查询集class

class MyCustomQuerySet(models.QuerySet):
    def get_by_tag(self, tag_name):
        return self.filter(post__pk__in=Post.objects.filter(tags__pk=tag_name))

    # more possible queryset methods ...

A) 如果您的经理只有查询集方法而没有其他自定义方法
那么您可以简单地从 QuerySet 创建它。

class MyModel(models.Model):
    objects = MyCustomQuerySet.as_manager()

B) 如果您的经理还需要其他不 return 查询集的方法:

class MyCustomManager(models.Manager):
    ...  # other methods

class MyModel(models.Model):
    objects = MyCustomManager.from_queryset(MyCustomQuerySet)()