首页 文章

从django中的查询集中获取第一个对象的最快方法?

提问于
浏览
156

通常我发现自己想要从Django中的查询集中获取第一个对象,或者如果没有't any. There are lots of ways to do this which all work. But I' m想知道哪个是最高性能的话,则返回 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-test时,这是一个非常耗费内存的事情 .

如何只使用一次数据库调用并且不使用异常对象搅拌内存?

8 回答

  • 280

    Django 1.6 (released Nov 2013)引入了convenience methods first()last() ,如果查询集没有返回任何对象,则会吞下生成的异常并返回 None .

  • 3

    正确的答案是

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

    Which can be used in:

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

    您不希望先将其转换为列表,因为这会强制对所有记录进行完整的数据库调用 . 只需执行上述操作即可完成第一项操作 . 您甚至可以使用 .order_by 来确保获得您想要的第一个 .

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

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

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

    YourModel.objects.all().first()
    

    这是比 .get()[0] 更好的方法,因为如果queryset为空,它不会抛出异常,因此,您不需要使用 exists() 进行检查

  • 49

    如果您计划经常获取第一个元素 - 您可以在此方向上扩展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()
    
  • 5

    它可以是这样的

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

    要么

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

    你应该使用django方法,比如exists . 它在那里供你使用 .

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

    这可能也有效:

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

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

相关问题