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
我想。对于我来说,这个答案对于计算单个标记的帖子数量也非常有用。谢谢你!