Django Count () dans les annotations multiples
disons que j'ai un modèle de forum simple:
class User(models.Model):
username = models.CharField(max_length=25)
...
class Topic(models.Model):
user = models.ForeignKey(User)
...
class Post(models.Model):
user = models.ForeignKey(User)
...
Maintenant, dites que je veux voir combien de sujets et de messages chaque utilisateur de sous-ensemble des utilisateurs a (par exemple, leur nom d'utilisateur commence par "ab").
donc si je fais une requête pour chaque poste et sujet:
User.objects.filter(username_startswith="ab")
.annotate(posts=Count('post'))
.values_list("username","posts")
Yeilds:
[('abe', 5),('abby', 12),...]
et
User.objects.filter(username_startswith="ab")
.annotate(topics=Count('topic'))
.values_list("username","topics")
rendements:
[('abe', 2),('abby', 6),...]
cependant, quand j'essaie d'annoter les deux pour obtenir une liste, j'obtiens quelque chose étrange:
User.objects.filter(username_startswith="ab")
.annotate(posts=Count('post'))
.annotate(topics=Count('topic'))
.values_list("username","posts", "topics")
rendements:
[('abe', 10, 10),('abby', 72, 72),...]
Pourquoi les sujets et messages multipliés? Je m'attendais à ceci:
[('abe', 5, 2),('abby', 12, 6),...]
Quelle serait la meilleure façon d'obtenir la bonne liste?
2 réponses
je pense que Count('topics', distinct=True)
devrait faire la bonne chose. Qui va utiliser COUNT(DISTINCT topic.id)
au lieu de COUNT(topic.id)
pour éviter les doublons.
User.objects.filter(
username_startswith="ab").annotate(
posts=Count('post', distinct=True)).annotate(
topics=Count('topic', distinct=True)).values_list(
"username","posts", "topics")
essayez d'ajouter distinct à votre dernier queryset:
User.objects.filter(
username_startswith="ab").annotate(
posts=Count('post')).annotate(
topics=Count('topic')).values_list(
"username","posts", "topics").distinct()
voir https://docs.djangoproject.com/en/1.3/ref/models/querysets/#distinct pour plus de détails, mais en gros vous obtenez des lignes dupliquées parce que les annotations couvrent plusieurs tables.