Tôi muốn lấy 10 trường hợp cuối cùng của một mô hình và có mã này:
Model.objects.all().order_by('-id')[:10]
Có đúng là trước hết hãy chọn tất cả các trường hợp, và sau đó chỉ lấy 10 trường hợp cuối cùng? Có phương pháp nào hiệu quả hơn không?
Tôi muốn lấy 10 trường hợp cuối cùng của một mô hình và có mã này:
Model.objects.all().order_by('-id')[:10]
Có đúng là trước hết hãy chọn tất cả các trường hợp, và sau đó chỉ lấy 10 trường hợp cuối cùng? Có phương pháp nào hiệu quả hơn không?
Câu trả lời:
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>]
Trên thực tế tôi nghĩ rằng việc LIMIT 10
nà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.
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.
Đú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.
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ố.
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ợ."