Подтвердить что ты не робот

Как добавить аннотационные данные в ответы на запрос ответа django-rest-framework?

Я генерирую агрегаты для каждого элемента в QuerySet:

def get_queryset(self):
    from django.db.models import Count
    queryset = Book.objects.annotate(Count('authors'))
    return queryset

Но я не получаю счет в ответе JSON.

благодарим вас заранее.

4b9b3361

Ответ 1

Запрос, возвращенный из get_queryset, содержит список вещей, которые будут проходить через сериализатор, который будет контролировать, как будут представлены объекты. Попробуйте добавить дополнительное поле в свой сериализатор книг, например:

author_count = serializers.IntegerField(
    source='author_set.count', 
    read_only=True
)

Ответ 2

Принятое решение попадет в базу данных столько раз, сколько будут возвращены результаты. Для каждого результата будет выполнен запрос count к базе данных.

Вопрос заключается в добавлении аннотаций к сериализатору, что более эффективно, чем выполнение запроса count для каждого элемента в ответе.

Решение для этого:

models.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...
    ...

serializers.py

class BookSerializer(serializers.ModelSerializer):
    authors = serializer.IntegerField()

    class Meta:
        model = Book
        fields = ('id', 'title', 'authors')

views.py

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.annotate(authors=Count('author'))
    serializer_class = BookSerializer
    ...

Это приведет к подсчету на уровне базы данных, избегая попадания в базу данных, чтобы получить количество авторов для каждого из возвращенных элементов Book.

Ответ 3

Решение Fiver попадет в db для каждого экземпляра в наборе запросов, поэтому, если у вас большой набор запросов, его решение создаст много запросов.

Я бы переопределил to_representation вашего сериализатора книг, он повторно использует результат из аннотации. Он будет выглядеть примерно так:

class BookSerializer(serializers.ModelSerializer):
     def to_representation(self, instance):
        return {'id': instance.pk, 'num_authors': instance.authors__count}

    class Meta:
        model = Book