从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 

另一种select是:

 qs = MyModel.objects.filter(blah = blah) try: return qs[0] except IndexError: return None 

这会生成一个单一的数据库调用,这是很好的。 但是需要在很多时候创build一个exception对象,当你真正需要的只是一个简单的if-test时,这是一个非常耗费内存的事情。

我怎样才能做到这一点,只需一个数据库调用,而不用exception对象搅动内存?

Django 1.6(2013年11月发布)引入了便利方法 first()last() ,它们捕获得到的exception,如果queryset不返回对象,则返回None

正确的答案是

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

哪些可用于:

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

你不想先把它变成一个列表,因为这会迫使一个完整的数据库调用所有的logging。 只要做到以上,它只会拉第一。 你甚至可以使用.order_by来确保你得到你想要的第一个。

一定要添加.get() ,否则你会得到一个QuerySet而不是一个对象。

 r = list(qs[:1]) if r: return r[0] return None 

现在,在Django 1.9中,您有查询集的first()方法。

 YourModel.objects.all().first() 

这是比.get()[0]更好的方法,因为如果queryset为空,则不会引发exception。Therafore,您不需要使用exists()

如果您打算经常获取第一个元素 – 您可以在这个方向上扩展QuerySet:

 class FirstQuerySet(models.query.QuerySet): def first(self): return self[0] class ManagerWithFirstQuery(models.Manager): def get_query_set(self): return FirstQuerySet(self.model) 

像这样定义模型:

 class MyModel(models.Model): objects = ManagerWithFirstQuery() 

像这样使用它:

  first_object = MyModel.objects.filter(x=100).first() 

它可以是这样的

 obj = model.objects.filter(id=emp_id)[0] 

要么

 obj = model.objects.latest('id') 

你应该使用Django的方法,就像存在。 它在那里给你使用它。

 if qs.exists(): return qs[0] return None 

这也可以工作:

 def get_first_element(MyModel): my_query = MyModel.objects.all() return my_query[:1] 

如果它是空的,则返回一个空列表,否则返回列表中的第一个元素。