2016-03-09 39 views
8

Trong Django ORM, làm cách nào để tạo một đối tượng Q luôn luôn là Sai?Luôn đối tượng Q sai

Điều này tương tự như câu hỏi về always True Q objects, nhưng ngược lại.

Lưu ý rằng điều này không làm việc:

Foobar.objects.filter(~Q()) # returns a queryset which gives all objects 

Tại sao tôi muốn có một đối tượng Q thay vì giá trị False đơn giản? Vì vậy mà tôi có thể kết hợp nó với các giá trị Q khác, như thế này ví dụ:

condition = always_true_q_object 
if something_or_other: 
    condition = condition | foobar_that_returns_a_q_object() 
if something_or_other2: 
    condition = condition | foobar_that_returns_a_q_object2() 
+0

Bạn có nghĩa là '.exclude (Q())'? .. – Sayse

+0

@Sayse Tôi có thể xem cách thức hoạt động. Tuy nhiên, tôi muốn một đối tượng Q luôn luôn là False, để tôi có thể sử dụng nó sau này để kết hợp với các đối tượng Q khác với logic AND và OR. – Flimm

+0

Nó có thể giúp đỡ nếu bạn có thể hiển thị [mcve] chính xác những gì bạn đang tìm kiếm – Sayse

Trả lời

9

gì về:

Q(pk__isnull=True) 

hoặc

Q(pk=None) 

Dường hacky, nhưng nó dường như làm việc . Ví dụ:

>>> FooBar.objects.filter(Q(x=10)|Q(pk__isnull=True)) 
[<FooBar: FooBar object>, ...] 
>>> FooBar.objects.filter(Q(x=10)&Q(pk__isnull=True)) 
[] 

Tuy nhiên, lưu ý rằng nó không hoạt động như bạn có thể mong đợi khi HOẶC có một sản phẩm nào là Q().

>>> FooBar.objects.filter(Q()|Q(pk__isnull=True)) 
[] 

Giải pháp này có thể sử dụng Q(pk__isnull=False) làm 'luôn đúng Q'.

>>> FooBar.objects.filter(Q(pk__isnull=False)|Q(pk__isnull=True)) 
[<FooBar: FooBar object>, ...] 
>>> FooBar.objects.filter(Q(pk__isnull=False)&Q(pk__isnull=True)) 
[] 
+4

Cần lưu ý rằng "nó không hoạt động như bạn có thể mong đợi khi OR có một' Q() trống rỗng "không phải do các giới hạn của phương thức' Q (pk = None) ', mà đơn giản là vì' Q() 'không phải là" đối tượng True Q ". Đó là "một đối tượng Q trống". Nó không thêm bất kỳ thông tin mới nào vào hệ thống. Nó không thay đổi gì cả. 'Q() | [bất cứ điều gì]' tương đương với '[bất cứ điều gì]'. –

+1

@LudwikTrammer đó là một lời giải thích tốt về lý do tại sao nó không hoạt động. Vì vậy, tôi nghĩ rằng một giải pháp có thể có thể là sử dụng 'Q (pk__isnull = False)' thay vì 'Q()' cho 'đối tượng True Q'. – Alasdair

5

Tôi vừa mới sử dụng Q(pk__in=[]) để thể hiện thành ngữ này.

Cảm thấy hơi ít hacky và có thể làm cho trình tối ưu hóa của DBMS hoạt động tốt hơn một chút.

4

Tôi không có đủ danh tiếng để nhận xét, nhưng câu trả lời của Sam Mason (Q(pk__in=[])) có lợi thế là nó thậm chí không thực hiện truy vấn cơ sở dữ liệu nếu được sử dụng một mình. Django (v1.10) có vẻ đủ thông minh để nhận ra rằng điều kiện là không thỏa mãn, và trả về một queryset trống mà không hỏi cơ sở dữ liệu.

$ ./manage.py shell_plus 

In [1]: from django.db import connection 

In [2]: FooBar.objects.filter(Q(pk__in=[])) 
Out[2]: <QuerySet []> 

In [3]: connection.queries 
Out[3]: [] 
+0

Khi nó chỉ là một bình luận, không sử dụng sai nút trả lời. Vì vậy, có thể bạn muốn cải thiện thêm một chút ... để biến điều này thành câu trả lời thực sự. – GhostCat

+0

Được rồi, nhưng Sam đã trả lời câu hỏi trước, tôi vừa có phụ lục cho câu trả lời của anh ấy. Tôi thực sự không biết ý bạn là gì "cải thiện thêm một chút" - danh tiếng của tôi? Kiến thức của tôi? Tôi chỉ muốn thêm một miếng ngon hữu ích để những người khác có thể hưởng lợi. – fwip

+0

@fwip Điều đó thực sự hữu ích khi biết, cảm ơn! – Flimm

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