从 django 中的查询集中获取第一个对象的最快方法?
我经常发现自己想要从 Django 的查询集中获取第一个对象,或者如果没有任何对象,则返回 None 。有很多方法可以做到这一点,而且都有效。但我想知道哪个性能最好。
qs = MyModel.objects.filter(blah = blah)
if qs.count() > 0:
return qs[0]
else:
return None
这会导致两次数据库调用吗?这看起来很浪费。这更快吗?
qs = MyModel.objects.filter(blah = blah)
if len(qs) > 0:
return qs[0]
else:
return None
另一种选择是:
qs = MyModel.objects.filter(blah = blah)
try:
return qs[0]
except IndexError:
return None
这会生成一个数据库调用,这很好。但很多时候需要创建一个异常对象,当您真正需要的只是一个简单的 if 测试时,这是一件非常占用内存的事情。
如何仅通过一次数据库调用来完成此操作,而不用异常对象搅动内存?
Often I find myself wanting to get the first object from a queryset in Django, or return None
if there aren't any. There are lots of ways to do this which all work. But I'm wondering which is the most performant.
qs = MyModel.objects.filter(blah = blah)
if qs.count() > 0:
return qs[0]
else:
return None
Does this result in two database calls? That seems wasteful. Is this any faster?
qs = MyModel.objects.filter(blah = blah)
if len(qs) > 0:
return qs[0]
else:
return None
Another option would be:
qs = MyModel.objects.filter(blah = blah)
try:
return qs[0]
except IndexError:
return None
This generates a single database call, which is good. But requires creating an exception object a lot of the time, which is a very memory-intensive thing to do when all you really need is a trivial if-test.
How can I do this with just a single database call and without churning memory with exception objects?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
Django 1.6(2013 年 11 月发布) 引入了 < a href="https://docs.djangoproject.com/en/dev/ref/models/querysets/#first" rel="noreferrer">便捷方法
first()
和last()
吞掉产生的异常,如果查询集没有返回对象,则返回None
。Django 1.6 (released Nov 2013) introduced the convenience methods
first()
andlast()
which swallow the resulting exception and returnNone
if the queryset returns no objects.您可以使用 数组切片:
它可以与
一起使用。 filter():
您不想首先将其转换为列表,因为这会强制对所有记录进行完整的数据库调用。只需执行上述操作,它只会拉第一个。您甚至可以使用
.order_by()
确保您获得您想要的第一个结果。请务必添加
.get()
否则你会得到一个 QuerySet 返回而不是一个物体。You can use array slicing:
Which can be used with
.filter()
:You wouldn't want to first turn it into a list because that would force a full database call of all the records. Just do the above and it will only pull the first. You could even use
.order_by()
to ensure you get the first you want.Be sure to add the
.get()
or else you will get a QuerySet back and not an object.现在,在 Django 1.9 中,您拥有用于查询集的
first()
方法。这是比
.get()
或[0]
更好的方法,因为如果查询集为空,它不会抛出异常,Therafore,您不需要使用检查存在()
Now, in Django 1.9 you have
first()
method for querysets.This is a better way than
.get()
or[0]
because it does not throw an exception if queryset is empty, Therafore, you don't need to check usingexists()
这也可以工作:
如果它为空,则返回一个空列表,否则返回列表中的第一个元素。
This could work as well:
if it's empty, then returns an empty list, otherwise it returns the first element inside a list.
如果您打算经常获取第一个元素 - 您可以朝这个方向扩展 QuerySet:
像这样定义模型:
并像这样使用它:
If you plan to get first element often - you can extend QuerySet in this direction:
Define model like this:
And use it like this:
可以是这样
或者
It can be like this
or
您应该使用 django 方法,例如存在的方法。它就在那里供您使用。
You should use django methods, like exists. Its there for you to use it.
您可以通过如下方式获取第一个对象:
另外,您还可以通过以下方式获取最后一个对象:
You can get the first object with these ways as shown below:
In addition, you can get the last object with these ways as shown below: