2010-03-11 13 views
19

Có sự khác biệt nào giữa bộ lọc và loại trừ trong django không? Nếu tôi cóBộ lọc Django và loại trừ

self.get_query_set().filter(modelField=x) 

và tôi muốn thêm tiêu chí khác, có sự khác biệt có ý nghĩa giữa hai dòng mã sau không?

self.get_query_set().filter(user__isnull=False, modelField=x) 

self.get_query_set().filter(modelField=x).exclude(user__isnull=True) 

được coi là thực hành tốt hơn hoặc chúng giống nhau về cả chức năng và hiệu suất?

Trả lời

16

Cả hai đều được đánh giá một cách lười biếng, vì vậy tôi mong đợi họ thực hiện tương đương. SQL có thể khác nhau, nhưng không có sự phân biệt thực sự.

+0

cảm ơn. vì vậy nó chỉ là vấn đề sở thích cá nhân? tôi chỉ muốn chắc chắn rằng tôi sẽ không làm điều gì đó không thể giải thích được. – Enrico

+2

@Enrico: Không thực sự, nó phụ thuộc vào những gì bạn muốn. Xem câu trả lời của tôi. Hiệu suất không quan trọng trong trường hợp này, chúng là hai phương pháp phục vụ các mục đích khác nhau. Đối với thế hệ SQL, tài liệu nói về '.exclude()': * Nhiều tham số được nối qua AND trong câu lệnh SQL nằm bên dưới, và toàn bộ điều được đính kèm trong một NOT(). * –

+0

@Felix. Cảm ơn. Tôi đoán câu hỏi chính của tôi - mà tôi có thể đã truyền đạt rõ ràng hơn là về hiệu suất của cả hai trong django và sau đó cuối cùng SQL. Từ nhận xét tiếp theo của bạn, có vẻ như người ta có thể hoạt động tốt hơn người khác nhưng chủ yếu dựa trên kết quả SQL. Tuy nhiên, thay đổi câu lệnh thứ hai thành '.exclude (user__isnull = True) .filter (modelField = x)' sau đó sẽ làm cho hai câu lệnh nhiều hơn hoặc bằng nhau một lần nữa. – Enrico

15

Loại trừ chung là đối diện với bộ lọc. Trong trường hợp này cả hai ví dụ đều hoạt động giống nhau.

đây:

self.get_query_set().filter(user__isnull=False, modelField=x) 

Bạn chọn mục mà người sử dụng lĩnh vực không phải là vô modelField có giá trị x

Trong trường hợp này:

self.get_query_set().filter(modelField=x).exclude(user__isnull=True) 

Trước tiên, bạn chọn mục mà modelField có giá trị x (cả người dùng trong null và người dùng không phải là null), sau đó bạn loại trừ các mục có trường người dùng rỗng.

Tôi nghĩ rằng trong trường hợp này, tốt hơn nên sử dụng tùy chọn đầu tiên, nó trông sạch hơn. Nhưng cả hai đều làm việc giống nhau.

9

Nó phụ thuộc vào những gì bạn muốn đạt được. Với các giá trị boolean, bạn có thể dễ dàng chuyển đổi giữa các số .exclude().filter() nhưng những gì về ví dụ: nếu bạn muốn nhận tất cả các bài viết ngoại trừ các bài viết từ tháng 3? Bạn có thể viết các truy vấn như

Posts.objects.exclude(date__month=3) 

Với .filter() nó sẽ là (nhưng tôi không chắc liệu này thực sự hoạt động):

Posts.objects.filter(date__month__in=[1,2,4,5,6,7,8,9,10,11,12]) 

hoặc bạn sẽ phải sử dụng một đối tượng Q.

Như tên hàm đã đề xuất, .exclude() được sử dụng để loại trừ bộ dữ liệu từ resultset. Đối với các giá trị boolean bạn có thể dễ dàng đảo ngược điều này và sử dụng .filter() thay vào đó, nhưng đối với các giá trị khác, điều này có thể phức tạp hơn.