2010-01-19 36 views
17

Lấy ví dụ từ: http://docs.djangoproject.com/en/dev/topics/db/aggregation/#filter-and-excludelọc chỉ trên Chú thích trong Django

Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book')) 

Liệu có cách nào để có bộ lọc chỉ áp dụng cho các chú thích, vì vậy nó sẽ trả lại tất cả các nhà xuất bản, với một số có một NUM_BOOKS = 0 ?

+0

Vì vậy, bạn muốn danh sách tất cả các nhà xuất bản, mỗi nhà xuất bản được chú thích với số lượng sách được đánh giá cao của họ? –

+0

Có và danh sách đó phải bao gồm các nhà xuất bản không có sách hoặc chỉ những sách có xếp hạng thấp. –

Trả lời

18

Bạn có thể sử dụng biến chú thích trong bộ lọc.

publishers=Publisher.objects.annotate(num_books=Count('book')).filter(num_books__gte=2) 
+0

Không, đây không phải là điều tôi muốn. –

+0

Uhhh ... bạn muốn gì ... – czarchaic

+0

Ý tôi là, tôi muốn tất cả các nhà xuất bản được trả lại và mỗi nhà xuất bản phải được chú thích với số lượng sách có xếp hạng cao. Vì vậy, bao gồm trong danh sách nhà xuất bản phải là nhà xuất bản có ít hơn 2 cuốn sách có xếp hạng cao và nhà xuất bản chỉ có sách có chất lượng thấp và nhà xuất bản không có sách. Hãy cho tôi biết nếu tôi có thể làm rõ điều đó tốt hơn. –

0

Bạn có thể thử một cái gì đó như:

Book.objects.values('publisher').annotate(num_books=Count('id')) 
+1

Đó sẽ là tổng số của tất cả các sách, không chỉ những cuốn sách có xếp hạng lớn hơn 3. –

10

Hm, tôi nghĩ rằng bạn phải sử dụng một extra clause:

Publisher.objects.extra(select={ 
    'num_books': 'SELECT COUNT(*) ' + \ 
       'FROM <your_app>_book ' + \ 
       'WHERE <your_app>_book.publisher_id = ' + \ 
         '<your_app>_publisher.id AND ' + \ 
         'rating > 3.0' 
}) 
+0

Đây là câu trả lời hay nhất mà tôi đã thấy cho đến nay. Nó sẽ được tốt đẹp nếu tôi không phải sử dụng sql liệu mặc dù. –

+0

Đúng vậy! Tuy nhiên, điều này không gây ra bất kỳ vấn đề tương thích nào. Nhưng xin vui lòng cho tôi biết, nếu bạn phát hiện ra một cách để làm điều này mà không cần sql thô! – Maccesch

+1

Bạn có thể sử dụng phương pháp QuerySet._as_sql (kết nối), để tạo truy vấn thô bằng chính Django. Little hack nhưng vẫn tốt hơn so với viết nó. – farincz

5
from django.db import models 

Publisher.objects.annotate(
    num_books=models.Sum(
     models.Case(
      models.When(
       book__rating__gt=3.0, 
       then=1, 
      ), 
      default=0, 
      output_field=models.IntegerField(), 
     ) 
    ) 
).filter(
    num_books=0, 
) 
+0

Điều đó có vẻ gần, ngoại trừ không lọc theo "num_books = 0" ở cuối. Tất cả các nhà xuất bản phải được trả lại. –

0

Tôi chỉ phải đối mặt với loại vấn đề. Và nếu sự can thiệp của tôi cho vấn đề và giải pháp dự kiến ​​là chính xác, đây là giải pháp làm việc của tôi:
Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0) Chỉ cần hoán đổi bộ lọc & vị trí chú thích. Điều này được thực hiện trong phiên bản Django 1.9

+0

Đó chính xác là mã tôi có trong câu hỏi của tôi (thậm chí không hoán đổi). Vấn đề tôi gặp phải là nó không hiển thị các nhà xuất bản có 0 cuốn sách. Tôi không muốn lọc tất cả các nhà xuất bản, tôi chỉ muốn lọc số lượng. –

+0

Xin lỗi, tôi quên chỉnh sửa mã mẫu của bạn. Nhưng đây là những gì tôi đã thực hiện khi tôi muốn sử dụng bộ lọc & chú thích trong queryset của tôi. Và thật không may, tôi chưa đọc rõ câu hỏi của bạn về nhà xuất bản sách 0. – pupil

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