Python 如何在django rest框架queryset响应中添加注释数据?
我正在为查询集中的每个项目生成聚合:Python 如何在django rest框架queryset响应中添加注释数据?,python,django,django-rest-framework,Python,Django,Django Rest Framework,我正在为查询集中的每个项目生成聚合: def get_queryset(self): from django.db.models import Count queryset = Book.objects.annotate(Count('authors')) return queryset 但是我没有得到JSON响应中的计数 提前感谢。从get\u queryset返回的queryset提供将通过序列化程序处理的内容列表,该序列化程序控制对象的表示方式。尝试在图书序列化程
def get_queryset(self):
from django.db.models import Count
queryset = Book.objects.annotate(Count('authors'))
return queryset
但是我没有得到JSON响应中的计数
提前感谢。从get\u queryset返回的queryset提供将通过序列化程序处理的内容列表,该序列化程序控制对象的表示方式。尝试在图书序列化程序中添加其他字段,如:
author_count = serializers.IntegerField(
source='author_set.count',
read_only=True
)
编辑:正如其他人所说,这不是为返回多个结果的情况添加计数的最有效方法,因为它会对每个实例的数据库产生影响。请参阅@José的答案以获得更有效的解决方案。Fiver的解决方案将针对查询集中的每个实例命中db,因此如果您有一个大型查询集,他的解决方案将创建大量查询 我将覆盖您的图书序列化程序的to_表示,它将重用注释的结果。它将看起来像:
class BookSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
return {'id': instance.pk, 'num_authors': instance.authors__count}
class Meta:
model = Book
被接受的解决方案将在返回结果时多次命中数据库。对于每个结果,将对数据库进行
count
查询
问题在于向序列化程序添加注释,这比对响应中的每个项执行count
查询要有效得多
解决办法是:
型号.py
class Author(models.Model):
name = models.CharField(...)
other_stuff = models...
...
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(...)
publication_year = models...
...
class BookSerializer(serializers.ModelSerializer):
authors = serializers.IntegerField()
class Meta:
model = Book
fields = ('id', 'title', 'authors')
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.annotate(authors=Count('author'))
serializer_class = BookSerializer
...
序列化程序.py
class Author(models.Model):
name = models.CharField(...)
other_stuff = models...
...
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(...)
publication_year = models...
...
class BookSerializer(serializers.ModelSerializer):
authors = serializers.IntegerField()
class Meta:
model = Book
fields = ('id', 'title', 'authors')
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.annotate(authors=Count('author'))
serializer_class = BookSerializer
...
视图.py
class Author(models.Model):
name = models.CharField(...)
other_stuff = models...
...
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(...)
publication_year = models...
...
class BookSerializer(serializers.ModelSerializer):
authors = serializers.IntegerField()
class Meta:
model = Book
fields = ('id', 'title', 'authors')
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.annotate(authors=Count('author'))
serializer_class = BookSerializer
...
这将使计数在数据库级别,避免点击数据库检索每个返回的
Book
项目的作者计数
Model.objects.annotate(
some_new_col=Case(
When(some_field=some_value, then=Value(something)),
# etc...
default=Value(something_default),
output_field=SomeTypeOfField(),
)
).filter()#etccc
解释器会抛出一个错误,something
不是相关的序列化程序的模型字段,这是一个解决方法。这并不好,但是如果您添加了一个方法一些新的\u col
,它会识别上面查询中的值。
下面这些就可以了
def some_new_col(self):
pass;
你能解释一下为什么Fiver的解决方案会产生很多疑问吗?我以为在执行queryset后会处理serializer字段,这将进行适当的联接/分组?我使用字段(source='annotated_field')
@DmitrySemenov创建了它。我认为源参数将引用一个方法,而不是一个变量。我以前的代码中有“source='author\u set.count'”,但结果生成了很多查询(您可以从调试器中看到),大多数查询都是重复的,并调用了count方法。您能否详细介绍一下创建后如何使用BookViewSet类?我正在尝试获得相同的结果,但一旦我拥有了ViewSet,我就不知道如何使用它。序列化程序。IntegerField()
需要read_=True
我想。对于我来说,这个答案对于计算单个标记的帖子数量也非常有用。谢谢你!