从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]
如果它是空的,则返回一个空列表,否则返回列表中的第一个元素。