Django a la nouvelle fonction annotate() pour les jeux de requête. Cependant, je n'arrive pas à le faire fonctionner correctement pour plusieurs annotations dans un même jeu de requête.Django annotate() plusieurs fois provoque de mauvaises réponses
Par exemple,
tour_list = Tour.objects.all().annotate(Count('tourcomment')).annotate(Count('history'))
Une visite peut contenir plusieurs entrées de tourcomment et de l'histoire. J'essaie d'obtenir combien de commentaires et d'entrées d'histoire existent pour cette tournée. Les valeurs
history__count and tourcomment__count
seront incorrectes. S'il n'y a qu'un seul appel annotate(), la valeur sera correcte.
Il semble y avoir une sorte d'effet multiplicatif provenant des deux LEFT OUTER JOIN
. Par exemple, si un tour a 3 historiques et 3 commentaires, 9 sera la valeur de comptage pour les deux. 12 histoires + 1 commentaire = 12 pour les deux valeurs. 1 histoire + 0 commentaire = 1 histoire, 0 commentaires (celui-ci arrive à renvoyer les valeurs correctes).
L'appel SQL résultant est:
SELECT `testapp_tour`.`id`, `testapp_tour`.`operator_id`, `testapp_tour`.`name`, `testapp_tour`.`region_id`, `testapp_tour`.`description`, `testapp_tour`.`net_price`, `testapp_tour`.`sales_price`, `testapp_tour`.`enabled`, `testapp_tour`.`num_views`, `testapp_tour`.`create_date`, `testapp_tour`.`modify_date`, `testapp_tour`.`image1`, `testapp_tour`.`image2`, `testapp_tour`.`image3`, `testapp_tour`.`image4`, `testapp_tour`.`notes`, `testapp_tour`.`pickup_time`, `testapp_tour`.`dropoff_time`, COUNT(`testapp_tourcomment`.`id`) AS `tourcomment__count`, COUNT(`testapp_history`.`id`) AS `history__count`
FROM `testapp_tour` LEFT OUTER JOIN `testapp_tourcomment` ON (`testapp_tour`.`id` = `testapp_tourcomment`.`tour_id`) LEFT OUTER JOIN `testapp_history` ON (`testapp_tour`.`id` = `testapp_history`.`tour_id`)
GROUP BY `testapp_tour`.`id`
ORDER BY `testapp_tour`.`name` ASC
J'ai essayé de combiner les résultats de deux QuerySets qui contiennent un seul appel à annoter(), mais cela ne fonctionne pas bien ... Vous ne pouvez pas vraiment garantir que la commande sera la même. et il semble trop compliqué et salissant donc j'ai cherché quelque chose de mieux ...
tour_list = Tour.objects.all().filter(operator__user__exact = request.user).filter(enabled__exact = True).annotate(Count('tourcomment'))
tour_list_historycount = Tour.objects.all().filter(enabled__exact = True).annotate(Count('history'))
for i,o in enumerate(tour_list):
o.history__count = tour_list_historycount[i].history__count
Merci pour toute aide. Stackoverflow a sauvé mes fesses dans le passé avec beaucoup de questions déjà répondues, mais je n'ai pas encore trouvé de réponse à celle-ci.
... qui est encore une solution horrible, car ce filtre simplement tous les doublons de l'énorme résultat – dragonroot
Cela fonctionne qu'avec Compter. J'ai un problème similaire avec un nombre et une somme, et bien que la valeur de distinct à vrai garde le nombre exact, la somme est encore multipliée – StephenTG
Aussi, pour une description de bug Sum, voir: https: //code.djangoproject .com/ticket/10060 – sobolevn