Django имеет новую новую функцию annotate() для запросов. Однако я не могу заставить его работать правильно для нескольких аннотаций в одном наборе запросов.
Например,
tour_list = Tour.objects.all().annotate( Count('tourcomment') ).annotate( Count('history') )
Тур может содержать несколько записей об экскурсиях и истории. Я пытаюсь получить, сколько комментариев и записей истории существует для этого тура. Полученный результат
history__count and tourcomment__count
Значения будут неверными. Если будет только один вызов annotate(), значение будет правильным.
Кажется, что существует какой-то мультипликативный эффект, исходящий от двух LEFT OUTER JOIN
s. Например, если тур имеет 3 истории и 3 комментария, 9 будет значением счета для обоих. 12 историй + 1 комментарий = 12 для обоих значений. 1 history + 0 comment = 1 history, 0 комментариев (это возвращает правильные значения).
Результирующий SQL-вызов:
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
Я попытался объединить результаты двух запросов, содержащих один вызов annotate(), но он не работает правильно... Вы не можете гарантировать, что заказ будет таким же. и это кажется слишком сложным и беспорядочным, поэтому я искал что-то лучшее...
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
Спасибо за любую помощь. Stackoverflow сохранил мою задницу в прошлом с большим количеством уже ответивших вопросов, но я еще не смог найти ответ на этот вопрос.