Je génère des agrégats pour chaque élément d'un QuerySet:
def get_queryset(self):
from Django.db.models import Count
queryset = Book.objects.annotate(Count('authors'))
return queryset
Mais je n'obtiens pas le décompte dans la réponse JSON.
merci d'avance.
L'ensemble de requêtes renvoyé par get_queryset fournit la liste des éléments qui passeront par le sérialiseur, qui contrôle la façon dont les objets seront représentés. Essayez d'ajouter un champ supplémentaire dans votre sérialiseur de livres, comme:
author_count = serializers.IntegerField(
source='author_set.count',
read_only=True
)
Edit: Comme d'autres l'ont dit, ce n'est pas le moyen le plus efficace d'ajouter des décomptes pour les cas où de nombreux résultats sont retournés, car il frappera la base de données pour chaque instance. Voir la réponse de @ José pour une solution plus efficace.
La solution acceptée frappera la base de données autant de fois que les résultats seront renvoyés. Pour chaque résultat, une requête count
vers la base de données sera effectuée.
La question consiste à ajouter des annotations au sérialiseur, ce qui est beaucoup plus efficace que de faire une requête count
pour chaque élément de la réponse.
Une solution pour cela:
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 = serializers.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
...
Cela fera le comptage au niveau de la base de données, en évitant de frapper la base de données pour récupérer le nombre d'auteurs pour chacun des éléments Book
retournés.
La solution de Fiver atteindra la base de données pour chaque instance du jeu de requêtes, donc si vous avez un grand jeu de requêtes, sa solution créera beaucoup de requêtes.
Je remplacerais le to_representation de votre sérialiseur Book, il réutilise le résultat du ( annotation . Cela ressemblera à quelque chose comme:
class BookSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
return {'id': instance.pk, 'num_authors': instance.authors__count}
class Meta:
model = Book