2009-08-12 21 views
21

Django có hàm chú thích() mới tuyệt vời cho các queryset. Tuy nhiên tôi không thể làm cho nó hoạt động đúng cho nhiều chú thích trong một bộ truy vấn đơn lẻ.Chú thích Django() nhiều lần gây ra các câu trả lời sai

Ví dụ,

tour_list = Tour.objects.all().annotate(Count('tourcomment')).annotate(Count('history')) 

Một tour du lịch có thể chứa nhiều tourcomment và lịch sử mục. Tôi đang cố gắng có bao nhiêu nhận xét và mục lịch sử tồn tại cho chuyến tham quan này. Kết quả

history__count and tourcomment__count 

giá trị sẽ không chính xác. Nếu chỉ có một chú thích() gọi giá trị sẽ chính xác.

Dường như có một số loại hiệu ứng nhân từ hai số LEFT OUTER JOIN s. Ví dụ: nếu chuyến tham quan có 3 lịch sử và 3 nhận xét, 9 sẽ là giá trị tính cho cả hai. 12 lịch sử + 1 nhận xét = 12 cho cả hai giá trị. 1 lịch sử + 0 bình luận = 1 lịch sử, 0 bình luận (điều này xảy ra để trả về các giá trị chính xác).

kết quả Cuộc gọi SQL là:

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 

Tôi đã cố gắng kết hợp các kết quả từ hai queryset có chứa một cuộc gọi duy nhất để chú thích(), nhưng nó không hoạt động đúng ... Bạn có thể không thực sự đảm bảo rằng thứ tự sẽ giống nhau. và có vẻ như quá phức tạp và lộn xộn nên tôi đã tìm kiếm thứ gì đó tốt hơn ...

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 

Cảm ơn bạn đã được trợ giúp. Stackoverflow đã lưu mông của tôi trong quá khứ với rất nhiều câu hỏi đã được trả lời, nhưng tôi đã không thể tìm thấy câu trả lời cho câu hỏi này.

Trả lời

0

Tôi không thể đảm bảo rằng điều này sẽ giải quyết được sự cố của bạn, nhưng hãy thử thêm .order_by() vào cuộc gọi của bạn. Đó là:

tour_list = Tour.objects.all().annotate(Count('tourcomment')).annotate(Count('history')).order_by() 

Lý do cho điều này là django cần phải chọn tất cả các trường trong mệnh đề ORDER BY, làm cho các kết quả giống hệt nhau được chọn. Bằng cách gắn thêm .order_by(), bạn đang xóa hoàn toàn mệnh đề ORDER BY, điều này ngăn cản điều này xảy ra. Xem the aggregation documentation để biết thêm thông tin về vấn đề này.

40

Cảm ơn nhận xét của bạn. Điều đó không hoàn toàn hiệu quả nhưng nó đã giúp tôi đi đúng hướng. Cuối cùng tôi đã có thể giải quyết điều này bằng cách thêm rõ rệt cho cả hai Count() gọi:

Count('tourcomment', distinct=True) 
+1

... mà vẫn là một giải pháp kinh khủng, vì điều này chỉ lọc ra tất cả các bản sao từ kết quả khổng lồ – dragonroot

+1

này cũng chỉ hoạt động với Đếm. Tôi đang gặp một vấn đề tương tự với Count và Sum, và trong khi thiết lập riêng biệt để đúng giữ Count chính xác, Sum vẫn đang được nhân – StephenTG

+0

Ngoài ra, đối với một mô tả lỗi 'Sum' thấy: https: //code.djangoproject .com/ticket/10060 – sobolevn

Các vấn đề liên quan