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)()
问题:我已经为模型实现了一个自定义管理器,其中只有一个名为 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)()