Django - giới hạn kết quả truy vấn


Câu trả lời:


304

Truy vấn Django là lười biếng. Điều đó có nghĩa là một truy vấn sẽ đánh vào cơ sở dữ liệu chỉ khi bạn yêu cầu cụ thể về kết quả.

Vì vậy, cho đến khi bạn in hoặc thực sự sử dụng kết quả của một truy vấn, bạn có thể lọc thêm mà không cần truy cập cơ sở dữ liệu.

Như bạn có thể thấy bên dưới mã của bạn chỉ thực hiện một truy vấn sql để chỉ tìm nạp 10 mục cuối cùng.

In [19]: import logging                                 
In [20]: l = logging.getLogger('django.db.backends')    
In [21]: l.setLevel(logging.DEBUG)                      
In [22]: l.addHandler(logging.StreamHandler())      
In [23]: User.objects.all().order_by('-id')[:10]          
(0.000) SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" ORDER BY "auth_user"."id" DESC LIMIT 10; args=()
Out[23]: [<User: hamdi>]

Tôi đã thử điều này trên mongoDB và nó nói CHỌN không được hỗ trợ. Làm thế nào để làm điều này trên mongoDB?
winux

@winux Vì đây là đặc trưng của Django, có vẻ như bạn có thể cần phải xem xét việc thiết lập Django để hoạt động cụ thể với cơ sở dữ liệu loại Mongo / NoQuery. Đó không phải là một thiết lập điển hình theo kinh nghiệm của tôi, liên quan đến thiết lập Django ORM tiêu chuẩn.
kẻ hèn nhát vô danh

38

Trên thực tế tôi nghĩ rằng việc LIMIT 10này sẽ được cấp cho cơ sở dữ liệu nên việc cắt lát sẽ không xảy ra trong Python mà là trong cơ sở dữ liệu.

Xem giới hạn-truy vấn để biết thêm thông tin.


Lưu ý rằng điều này sẽ không hoạt động đối với các truy vấn cũng cần lọc, vì bạn không thể lọc sau khi cắt.
Mike 'Pomax' Kamermans

2
Vì vậy, lọc đầu tiên hơn lát nó. Cảm ơn Davor cho liên kết!
Vyachez

13

Có vẻ như giải pháp trong câu hỏi không còn hoạt động với Django 1.7 nữa và gây ra lỗi: "Không thể sắp xếp lại truy vấn sau khi đã thực hiện một lát cắt"

Theo tài liệu https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets buộc tham số Bước bước của cú pháp Python đánh giá Truy vấn. Nó hoạt động theo cách này:

Model.objects.all().order_by('-id')[:10:1]

Tôi vẫn tự hỏi nếu giới hạn được thực thi trong SQL hoặc Python thì toàn bộ mảng kết quả được trả về. Không có gì tốt để lấy danh sách lớn vào bộ nhớ ứng dụng.


Ngay cả giải pháp này cũng không hoạt động với django> = 1.8 được thử nghiệm.
sonus21

3

Đúng. Nếu bạn muốn tìm nạp một tập hợp con các đối tượng giới hạn, bạn có thể với đoạn mã dưới đây:

Thí dụ:

obj=emp.objects.all()[0:10]

Bắt đầu 0 là tùy chọn, vì vậy

obj=emp.objects.all()[:10]

Đoạn mã trên trả về 10 trường hợp đầu tiên.


1

Là một bổ sung và quan sát cho các câu trả lời hữu ích khác, đáng chú ý rằng thực sự làm việc [:10]cắt lát sẽ trả về 10 yếu tố đầu tiên của danh sách , chứ không phải 10 ...

Để có được 10 người cuối cùng bạn nên làm [-10:]thay thế (xem tại đây ). Điều này sẽ giúp bạn tránh sử dụng order_by('-id')với -để đảo ngược các yếu tố.


1
Tôi đã thử điều này và nhận được "lập chỉ mục tiêu cực không được hỗ trợ."
bparker

@DarkCygnus Product.objects.filter(~Q(price=0))[-5:]gây ra lỗi tương tự cho tôi: " Lập chỉ mục tiêu cực không được hỗ trợ."
bersam

Điều này không hoạt động trong django trên một bộ truy vấn: code.djangoproject.com/ticket/13089 Nếu bạn chuyển đổi bộ truy vấn thành một danh sách, nó sẽ hoạt động.
valem
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.