在Django中从查询集中获取第一个对象的最快方法是什么?

302 投票
9 回答
359218 浏览
提问于 2025-04-16 12:34

我经常想从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

这种方法只会生成一次数据库调用,这样很好。但很多时候需要创建一个异常对象,这在内存上消耗很大,而你其实只需要做一个简单的判断。

我怎么才能只用一次数据库调用,并且不因为异常对象而浪费内存呢?

9 个回答

58

在Django 1.9中,你可以使用first()这个方法来处理查询集。

YourModel.objects.all().first()

这个方法比.get()或者用[0]更好,因为如果查询集是空的,它不会抛出错误。因此,你不需要再用exists()来检查是否有数据。

174

你可以使用 数组切片

Entry.objects.all()[:1].get()

这可以和 .filter() 一起使用:

Entry.objects.filter()[:1].get()

你不想先把它变成一个列表,因为那样会强制从数据库中获取所有记录,这样会浪费资源。只需按照上面的做法,它只会提取第一个记录。你甚至可以使用 .order_by() 来确保你得到的是你想要的第一个记录。

记得加上 .get(),否则你会得到一个 查询集,而不是一个具体的对象。

486

Django 1.6(发布于2013年11月) 引入了两个非常方便的方法,分别是 first()last()。这两个方法的好处是,如果你查询的数据没有结果,它们不会报错,而是会返回 None,也就是说返回一个空值。

撰写回答