更好的选项来检查特定实例是否存在django

Asw*_*esh 10 django models

检查实例是否存在,这两者中哪一个是更好和更有效的选项.最多只能返回一条记录.

1)使用过滤器选项,看它是否存在:

x = MyObject.objects.filter(someField=someValue).count()
if x:
    #Instance exists
Run Code Online (Sandbox Code Playgroud)

2)使用get并检查异常:

try:
    x = MyObject.objects.get(someField=someValue)
except MyObject.DoesNotExist:
    #Do Something
Run Code Online (Sandbox Code Playgroud)

上面提到的哪种方法有效或更"Djangoic"?

Rah*_*pta 17

甚至更好的方法是使用.exists()检查一个特定实例的存在与否.

MyObject.objects.filter(someField=someValue).exists() # return True/False
Run Code Online (Sandbox Code Playgroud)

来自.exists()文档:

True如果QuerySet包含任何结果,False则返回,否则返回.这尝试以尽可能最简单和最快的方式执行查询,但它确实执行与普通QuerySet查询几乎相同的查询.

exists() 对于与QuerySet中的对象成员资格相关的搜索以及QuerySet中任何对象的存在,特别是在大型QuerySet的上下文中,它非常有用.

文档中的一些示例:

示例1:查找具有唯一字段的模型是否为其成员 QuerySet

查找具有唯一字段(例如primary_key)的模型是否是a的成员的最有效方法QuerySet是:

entry = Entry.objects.get(pk=123)

if some_queryset.filter(pk=entry.pk).exists(): # faster
    print("Entry contained in queryset")
Run Code Online (Sandbox Code Playgroud)

这将比以下更快,这需要评估和迭代整个查询集:

if entry in some_queryset: # slower 
   print("Entry contained in QuerySet")
Run Code Online (Sandbox Code Playgroud)

示例2:查找查询集是否包含任何项目

要查找查询集是否包含任何项,请使用以下方法

if some_queryset.exists(): # faster
    print("There is at least one object in some_queryset")
Run Code Online (Sandbox Code Playgroud)

将比以下更快:

if some_queryset: # slower
    print("There is at least one object in some_queryset")
Run Code Online (Sandbox Code Playgroud)

...但不是很大程度上(因此需要一个大的查询集来提高效率).

如果我还想使用该对象,该怎么办?

如果你想使用该对象,如果它存在,那么使用.exists()效率不高,那么你将执行2个查询.第一个查询将检查是否存在,第二个查询将是获取对象.

  • 请注意,使用 `MyObject.objects.filter(foo='bar').exists()` 仍然会从数据库中获取整个对象及其所有字段。使用 MyObject.objects.only('foo').filter(foo='bar').exists() 可以更快,它将查询更改为仅获取正在过滤的同一列。如果您要过滤的字段是主键或具有索引,这尤其有用,因为它允许数据库优化为仅索引查询。YMMV 取决于模型底层的特定数据库。 (4认同)

Alv*_*aro 5

exists当尝试查找是否存在单个实例时,我不喜欢该解决方案。

在这种情况下,我会选择鸭子输入(第二种选择),因为它更像pythonic:

try:
    instance = MyModel.objects.get(id=1)
except MyModel.DoesNotExist:
    print "Too bad"
else:
    instance.do_something()
Run Code Online (Sandbox Code Playgroud)