Cách đúng đắn để xác thực nếu một đối tượng tồn tại trong chế độ xem django mà không trả về 404 là gì?


91

Tôi cần xác minh nếu một đối tượng tồn tại và trả về đối tượng, sau đó dựa trên đó thực hiện các hành động. Cách phù hợp để làm điều đó mà không trả về 404 là gì?

try:
    listing = RealEstateListing.objects.get(slug_url = slug)
except:
    listing = None

if listing:

Rasiel, tôi có thể đề nghị bạn xem xét chấp nhận câu trả lời khác không? Nó có vẻ là cách chính xác để làm điều này và đã được ủng hộ khá nhiều so với câu trả lời được chấp nhận.
Azendale

1
Tôi có thể xem xét nó, tuy nhiên tồn tại đã được giới thiệu trong Django 1.2 được phát hành vào ngày 17 tháng 5 năm 2010, Nếu bạn nhận thấy câu hỏi của tôi đã được gửi vào năm 09 ... thì đây là câu trả lời chính xác vào thời điểm đó. Nếu Exists () bây giờ được coi là cách tốt nhất để làm điều đó, tôi đoán sẽ đúng về mặt ngữ nghĩa nếu chọn câu trả lời thứ hai, phải không?
Rasiel,

Rasiel, có lý khi đó là câu trả lời chính xác vào thời điểm đó. Nhưng các trang web stackoverflow dường như tập trung nhiều vào việc xây dựng một tập hợp các câu hỏi hay / chính thức với câu trả lời tốt nhất vì các trang web đang tìm giải pháp cho các vấn đề của mọi người. Do đó, gợi ý của tôi để chọn câu trả lời "chính thức đúng".
Azendale

Các if listing:phải là một else:.
Chronial

Câu trả lời:


116

Tôi sẽ không sử dụng trình bao bọc 404 nếu bạn không được cấp 404. Đó là lạm dụng mục đích. Thay vào đó, chỉ cần bắt DoesNotExist.

try:
    listing = RealEstateListing.objects.get(slug_url=slug)
except RealEstateListing.DoesNotExist:
    listing = None

1: Vâng, đây là một giải pháp tốt hơn so với một được chấp nhận, nếu bạn không muốn 404.
Carl Meyer

yap, điều này dường như là giải pháp tốt hơn
Rasiel

3
Giải pháp này hoạt động tốt hơn exists()nếu bạn cần làm gì đó với đối tượng.
SaeX

2
Tôi muốn thêm values_list('id', flat=True). nếu tôi cần phải chỉ thấy nếu tồn tạilisting = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
erajuan

Điều tôi thấy lạ về cú pháp này là nó RealEstateListing.DoesNotExistđang đề cập đến mô hình, chứ không phải bản thân đối tượng. Tại sao nó không RealEstateListing.objects.get(slug_url=slug).DoesNotExist?
Maxim Vallee

198

Bạn cũng có thể làm:

if not RealEstateListing.objects.filter(slug_url=slug).exists():
    # do stuff...

Đôi khi sử dụng try: except:khối rõ ràng hơn và những lần khác một lớp lót exists()làm cho mã trông rõ ràng hơn ... tất cả phụ thuộc vào logic ứng dụng của bạn.



7
đây là cách tốt hơn và cần có câu trả lời
Jharwood

3
Tôi cho rằng điều exists()đó không hoạt động với get(), phải không?
Eduard Luca

8
Lưu ý rằng giải pháp này chỉ hợp lệ nếu bạn không sử dụng đối tượng được đề cập. Nếu không (như trong tình huống OP) thì nó sai và chậm hơn rất nhiều so với giải pháp được chấp nhận: Nếu bạn thực hiện get()muộn hơn, nó sẽ gửi một truy vấn thứ hai đến cơ sở dữ liệu.
Chronial

1
Nếu bạn đang kiểm tra sự tồn tại để làm điều gì đó với đối tượng (nếu nó tồn tại), thì tôi sẽ thích try-excepthơn exists().
Jithin Pavithran

7
listing = RealEstateListing.objects.filter(slug_url=slug).first() 

2
Đây là giải pháp tốt nhất nếu bạn cần sử dụng đối tượng tiềm năng sau này, vì nó chỉ yêu cầu một lần gán và nó tránh phải sử dụng khối thử / ngoại trừ. Lưu ý rằng bạn có thể kiểm tra sự tồn tại sau này đơn giản vớiif listing:
Michael Hays

Tránh thử / ngoại trừ là thực hành không tốt. Một trong những khía cạnh quan trọng nhất của Phát triển phần mềm là khả năng kiểm soát các Ngoại lệ, điều này để có thể cung cấp trải nghiệm người dùng tốt. Cho mọi người biết khi có điều gì đó không hoạt động bình thường. Thứ hai; nếu bạn muốn kiểm tra sự tồn tại của một QuerySet, hãy sử dụng .exists () nếu không thì là một đối tượng. Kiểm tra sự tồn tại bằng khóa chính của chúng .... if object.pk: // run code () Truy vấn này nhanh hơn cách lấy tất cả dữ liệu của đối tượng. Bạn chỉ muốn biết nếu tồn tại.
Wolfgang Leon

2
Đã có một giải pháp sử dụng thử / ngoại trừ và .exists(). Tôi nghĩ rằng nên có nhiều câu trả lời khác nhau về cách thực hiện mọi việc trong SO. Có thể điều này tốt hơn cho những người cũng muốn sử dụng đối tượng nếu nó tồn tại. Tôi sẽ không đưa ra bất kỳ quy tắc nào nếu nên tránh hoặc không nên thử / ngoại trừ. Đôi khi nó tốt, và đôi khi nó tệ, chẳng hạn như nếu bạn chỉ muốn tạo mã rất nhỏ gọn.
Henrik Heino

0

Tôi sẽ làm điều đó đơn giản như sau:

listing = RealEstateListing.objects.filter(slug_url=slug)
if listing:
    # do stuff

Tôi không thấy cần phải thử / bắt. Nếu có một số đối tượng tiềm ẩn trong kết quả, thì hãy sử dụng first () như được hiển thị bởi người dùng Henrik Heino


Trừ khi bạn thực hiện .first () trên bộ truy vấn hoặc .first () trong điều kiện, điều này sẽ luôn trả về True.
B.Adler
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.