Django trong / không trong truy vấn


100

Tôi đang cố gắng tìm cách viết một truy vấn kiểu 'không phải trong' trong django. Ví dụ, cấu trúc truy vấn tôi đang nghĩ đến sẽ trông như thế này.

select table1.* 
from table1
where table1.id not in 
(
  select table2.key_to_table1
  from table2 
  where table2.id = some_parm 
)

Cú pháp django sẽ trông như thế nào giả sử các mô hình được gọi là table1 và table2?

Câu trả lời:


163
table1.objects.exclude(id__in=
    table2.objects.filter(your_condition).values_list('id', flat=True))

Hàm loại trừ hoạt động giống như Nottoán tử mà bạn yêu cầu. Thuộc tính flat = Trueyêu cầu table2truy vấn trả về value_listdưới dạng danh sách một cấp. Vì vậy, ... cuối cùng, bạn đang nhận được một danh sách IDstừ table2, mà bạn sẽ sử dụng để xác định điều kiện trong table1đó, sẽ bị từ chối bởi hàm loại trừ.


3
Tôi cũng gặp sự cố với hàm tạo danh sách [table2 ...] -> list (table2 ...) làm việc cho tôi.
RickyA

3
chỉnh: table1.objects.exclude (id__in = table2.objects.filter (your_condition) .values_list ( 'id', phẳng = True))
Richard

1
Đang cố gắng sử dụng giải pháp này và gặp sự cố, vì vậy nếu nó xảy ra với bất kỳ ai khác ... Objs=Tbl1.objects.filter(...); IDs=Objs.values_list('id', flat=True); Objs.delete(); Tbl2.objects.filter(id__in=IDs')Điều này không hoạt động vì ID thực sự là một đối tượng QuerySet. Khi tôi xóa các hàng mà nó bắt nguồn, nó không còn hoạt động với các truy vấn khác. Các giải pháp được Tbl2.objects.filter(id__in=list(IDs))- biến nó thành một danh sách
Dakusan

1
Tùy thuộc vào ngữ cảnh, nếu bộ lọc giống như "có số lượng (xx) == yy" thì nó sẽ nhanh hơn 100 lần để sử dụng annotate()(thời gian cho tôi 1,0497902309998608 so với 0,00514069400014705)
Olivier Pons

10

với các mô hình này:

class table1(models.Model):
    field1 = models.CharField(max_length=10)      # a dummy field

class table2(models.Model):
    key_to_table1 = models.ForeignKey(table1)

bạn sẽ có được những gì bạn muốn bằng cách sử dụng:

table1.objects.exclude(table2=some_param)

1
Điều này vẫn có khả năng bạn lấy rất nhiều bản ghi từ db một cách không cần thiết.
Jay Taylor

5
table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])

1

Bạn có thể viết một tra cứu tùy chỉnh cho các truy vấn Django:

Từ tài liệu hướng dẫn : "Hãy bắt đầu với một tra cứu tùy chỉnh đơn giản Chúng tôi sẽ viết một tra cứu tùy chỉnh ne mà làm việc đối diện với chính xác . Author.objects.filter (name__ne = 'Jack') sẽ dịch sang SQL: "author"."name" <> 'Jack'"

from django.db.models import Lookup

class NotEqual(Lookup):
    lookup_name = 'ne'

    def as_sql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return '%s <> %s' % (lhs, rhs), params

-16
[o1 for o1 in table1.objects.all() if o1.id not in [o2.id for o2 in table2.objects.filter(id=some_parm)]]

Hoặc tốt hơn

not_in_ids = [obj.id for obj in table2.objects.filter(id=some_parm)]
selected_objects = [obj for obj in table1.objects.iterator() if obj.id not in not_in_ids]

12
Lặp lại mọi hàng trong bảng. gg
Rebs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.