2009-09-07 37 views
104

Thành ngữ được đề nghị để kiểm tra xem truy vấn có trả về bất kỳ kết quả nào không?
Ví dụ:Kiểm tra truy vấn trống trong Django

orgs = Organisation.objects.filter(name__iexact = 'Fjuk inc') 
# If any results 
    # Do this with the results without querying again. 
# Else, do something else... 

Tôi cho rằng có nhiều cách khác nhau của việc kiểm tra này, nhưng tôi muốn biết làm thế nào một người dùng có kinh nghiệm Django sẽ làm điều đó. Hầu hết các ví dụ trong các tài liệu chỉ cần bỏ qua trường hợp không có gì đã được tìm thấy ...

Trả lời

101
if not orgs: 
    # Do this... 
else: 
    # Do that... 
+3

này dường như cũng được ưa thích trong tài liệu, ví dụ: https: // docs.djangoproject.com/en/1.8/topics/http/shortcuts/#id7 – Wtower

+0

@Wtower Mã bạn tham chiếu có hợp đồng để tăng 404 nếu biểu thức lọc không đạt bất kỳ bản ghi nào hoặc để tạo ra một 'danh sách' của kết quả nếu có hồ sơ. Mã sẽ xuất hiện trên cơ sở dữ liệu một lần. Nếu họ đã sử dụng 'exist()' hoặc 'count()' để kiểm tra đầu tiên xem liệu sẽ có các bản ghi được trả về hay không, chúng sẽ nhấn cơ sở dữ liệu hai lần (một lần để kiểm tra, một lần để lấy các bản ghi). Đây là một tình huống cụ thể. Nó không đòi hỏi rằng trong trường hợp * chung, phương thức ưa thích để biết liệu một truy vấn sẽ trả về các bản ghi là sử dụng làm 'if queryset: ...' – Louis

+1

@Louis mã tôi tham chiếu chỉ là một ví dụ mà nó chứa một dòng 'if not my_objects:' để chứng minh rằng đây là cách chúng thực hiện trong tài liệu. Tất cả những thứ khác hoàn toàn không liên quan nên tôi không hiểu điểm của bạn. Họ cũng có thể kiếm được một nghìn truy vấn và nó vẫn hoàn toàn không liên quan vì đây không phải là điểm của câu trả lời này, mà tôi làm rõ rằng tôi đồng ý. – Wtower

3

Cách hiệu quả nhất (trước django 1.2) là thế này:

if orgs.count() == 0: 
    # no results 
else: 
    # alrigh! let's continue... 
+3

.exists() dường như thậm chí còn hiệu quả hơn – dzida

+3

Ngoại trừ .exists() đã được thêm vài tháng sau khi nhận xét của tôi và Django 1.2 (kết hợp API) đã được phát hành ~ 8 tháng sau đó. Nhưng cảm ơn bạn đã bỏ phiếu và không bận tâm kiểm tra sự thật. – Bartosz

+4

Xin lỗi, tôi đã thêm chỉnh sửa nhỏ vào câu trả lời của bạn để làm cho câu trả lời chính xác hơn và được bình chọn tích cực hơn. – dzida

14

Nếu bạn có một số lượng lớn các đối tượng, điều này có thể (ở lần) được nhanh hơn:

try: 
    orgs[0] 
    # If you get here, it exists... 
except IndexError: 
    # Doesn't exist! 

trên một dự án tôi đang làm việc trên với một cơ sở dữ liệu khổng lồ, not orgs là 400+ ms và orgs.count() là 25 0ms. Trong trường hợp sử dụng phổ biến nhất của tôi (những trường hợp có kết quả), kỹ thuật này thường giảm xuống dưới 20 mili giây. (Một trường hợp tôi tìm thấy, đó là 6.)

Có thể lâu hơn nữa, tất nhiên, tùy thuộc vào khoảng cách mà cơ sở dữ liệu tìm để tìm kết quả. Hoặc thậm chí nhanh hơn, nếu nó tìm thấy một cách nhanh chóng; YMMV.

CHỈNH SỬA: này sẽ thường chậm hơn orgs.count() nếu không tìm thấy kết quả, đặc biệt nếu điều kiện bạn đang lọc là hiếm; kết quả là, nó đặc biệt hữu ích trong các chức năng xem nơi bạn cần đảm bảo rằng khung nhìn tồn tại hoặc ném Http404. (Ở đâu, người ta sẽ hy vọng, mọi người đang yêu cầu các URL tồn tại thường xuyên hơn không.)

134

Kể từ phiên bản 1.2, Django có QuerySet. exists() phương pháp đó là hiệu quả nhất:

if orgs.exists(): 
    # Do this... 
else: 
    # Do that... 

Nhưng nếu bạn đang đi để đánh giá QuerySet anyway nó là tốt hơn để sử dụng:

if orgs: 
    ... 

Để biết thêm thông tin read QuerySet.exists() documentation.

5

Tôi không đồng ý với vị

if not orgs: 

Nó phải là

if not orgs.count(): 

Tôi đã có cùng một vấn đề với một tập kết quả khá lớn (~ 150k kết quả). Toán tử không bị quá tải trong QuerySet, do đó kết quả thực sự được giải nén dưới dạng danh sách trước khi kiểm tra được thực hiện. Trong trường hợp của tôi thời gian thực hiện đã đi xuống bởi ba đơn đặt hàng.

+4

_ \ _ nonzero _ \ _ đã bị quá tải trong QuerySet. Nếu kết quả không được lưu trữ (nó không bao giờ là ngày đầu tiên sử dụng queryset) hành vi của _ \ _ nonzero _ \ _ là lặp qua tất cả các phần tử trong queryset. Điều này rất tệ nếu tập hợp lớn. – hedleyroos

9

Để kiểm tra sự trống rỗng của một queryset:

if orgs.exists(): 
    # Do something 

hoặc bạn có thể kiểm tra một mục đầu tiên trong một queryset, nếu nó không tồn tại nó sẽ trở lại None:

if orgs.first(): 
    # Do something 
+1

'nếu orgs.exists()' được bao phủ bởi một [answer] (http://stackoverflow.com/a/2373793/1906307) đã được cung cấp khoảng 5 năm trước thời điểm này. Điều duy nhất mà câu trả lời này mang lại cho bảng là * có lẽ * mới là 'if orgs.first()'. (Thậm chí điều này có thể gây tranh cãi: có khác biệt đáng kể so với việc thực hiện 'tổ chức [0]' [đề xuất] (http://stackoverflow.com/a/2098092/1906307) khoảng 5 năm trước không?) Bạn nên phát triển phần đó của câu trả lời: khi nào người ta muốn làm điều này ** thay vì ** các giải pháp khác được đề xuất trước đó? – Louis

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