验证对象是否存在于Django视图中而不返回404的正确方法是什么?


91

我需要验证对象是否存在并返回该对象,然后根据该行为执行操作。什么是不返回404的正确方法?

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

if listing:

拉西尔,我可以建议您考虑接受其他答案吗?这似乎是正确的方法,并且比公认的答案要高得多。
Azendale 2015年

1
我可以考虑一下,但是存在于Django 1.2中,该版本于2010年5月17日发布,如果您注意到我的问题是在09年提交的,那是当时的正确答案。如果现在认为Exists()是最好的方法,那么我认为选择第二个答案在语义上是正确的,对吗?
Rasiel 2015年

Rasiel,这在当时是正确的答案,这是有道理的。但是,stackoverflow网站似乎不仅要建立一组具有最佳答案的良好/官方问题,还需要寻找人们问题的解决方案。因此,我建议选择现在“正式正确”的答案。
Azendale 2015年

if listing:应该是else:
慢性的

Answers:


116

如果您没有获得404,我就不会使用404包装器。这是对意图的滥用。只需捕获DoesNotExist,即可。

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

+1:是的,如果您不想要404,这是比接受的解决方案更好的解决方案。–
卡尔·迈耶

是的,这似乎是更好的解决方案
Rasiel

3
该解决方案比exists()您需要对对象执行某些操作的效果更好。
SaeX 2015年

2
我喜欢补充values_list('id', flat=True)。如果我只是需要看是否存在listing = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
erajuan

我对这种语法感到奇怪的是,RealEstateListing.DoesNotExist它引用的是模型,而不是对象本身。为什么不RealEstateListing.objects.get(slug_url=slug).DoesNotExist呢?
Maxim Vallee

198

您也可以这样做:

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

有时使用try: except:块更清晰,而有时使用单行exists()代码可使代码看起来更清晰……全部取决于您的应用程序逻辑。



7
这是更好的方法,应该有答案
Jharwood 2012年

3
我假设这exists()不适用于get()吧?
爱德华·卢卡

8
请注意,此解决方案仅在您不打算使用有问题的对象时才有效。否则(例如在OP中),这是错误的,并且比公认的解决方案要慢得多:如果get()稍后再执行,它将向数据库发送第二个查询。
慢性的

1
如果您要检查是否存在要对该对象做某事(如果存在),那么我将优先try-exceptexists()
Jithin Pavithran

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

2
如果您以后需要使用潜在对象,这是最佳解决方案,因为它只需要分配一次,并且避免了使用try / except块。请注意,您以后可以简单地通过if listing:
Michael Hays

避免尝试/例外是不好的做法。软件开发最重要的方面之一是控制异常的可用性,以便能够提供良好的用户体验。让人们知道什么时候某些东西不能正常工作。第二; 如果要测试QuerySet的存在,请使用.exists(),否则为对象。使用主键测试是否存在.... if object.pk://运行code()此查询比检索对象的所有数据快得多。您只想知道是否存在。
Wolfgang Leon

2
已经有使用try / except和的解决方案.exists()。我认为在SO中有多个不同的答案如何做事情是个好主意。对于那些也想使用该对象(如果存在)的人来说,这可能更好。如果不会避免使用try / except,我不会制定任何规则。例如,如果您只想编写非常紧凑的代码,则有时是好的,有时是不好的。
亨里克·海诺

0

我将简单地做如下:

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

我认为没有必要尝试/抓住。如果结果中可能存在多个对象,则使用first(),如用户Henrik Heino所示


除非您对查询集执行.first()或条件查询中的.first(),否则它将始终返回True。
B.Adler
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.