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

发布于 2024-10-19 05:05:34 字数 665 浏览 2 评论 0原文

我经常发现自己想要从 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

未蓝澄海的烟 2024-10-26 05:05:34

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() and last() which swallow the resulting exception and return None if the queryset returns no objects.

z祗昰~ 2024-10-26 05:05:34

您可以使用 数组切片

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

它可以与 一起使用。 filter():

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

您不想首先将其转换为列表,因为这会强制对所有记录进行完整的数据库调用。只需执行上述操作,它只会拉第一个。您甚至可以使用 .order_by() 确保您获得您想要的第一个结果。

请务必添加 .get() 否则你会得到一个 QuerySet 返回而不是一个物体。

You can use array slicing:

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

Which can be used with .filter():

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

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.

|煩躁 2024-10-26 05:05:34

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

YourModel.objects.all().first()

这是比 .get()[0] 更好的方法,因为如果查询集为空,它不会抛出异常,Therafore,您不需要使用检查存在()

Now, in Django 1.9 you have first() method for querysets.

YourModel.objects.all().first()

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 using exists()

时光是把杀猪刀 2024-10-26 05:05:34
r = list(qs[:1])
if r:
  return r[0]
return None
r = list(qs[:1])
if r:
  return r[0]
return None
夏夜暖风 2024-10-26 05:05:34

这也可以工作:

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

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

This could work as well:

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

if it's empty, then returns an empty list, otherwise it returns the first element inside a list.

孤云独去闲 2024-10-26 05:05:34

如果您打算经常获取第一个元素 - 您可以朝这个方向扩展 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()

If you plan to get first element often - you can extend QuerySet in this direction:

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


class ManagerWithFirstQuery(models.Manager):
    def get_query_set(self):
        return FirstQuerySet(self.model)

Define model like this:

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

And use it like this:

 first_object = MyModel.objects.filter(x=100).first()
咽泪装欢 2024-10-26 05:05:34

可以是这样

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

或者

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

It can be like this

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

or

obj = model.objects.latest('id')
暮凉 2024-10-26 05:05:34

您应该使用 django 方法,例如存在的方法。它就在那里供您使用。

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

You should use django methods, like exists. Its there for you to use it.

if qs.exists():
    return qs[0]
return None
心舞飞扬 2024-10-26 05:05:34

您可以通过如下方式获取第一个对象:

MyModel.objects.first()
MyModel.objects.all().first()
MyModel.objects.all()[0]
MyModel.objects.filter().first()
MyModel.objects.filter()[0]

另外,您还可以通过以下方式获取最后一个对象:

MyModel.objects.last()
MyModel.objects.all().last()
MyModel.objects.filter().last()

You can get the first object with these ways as shown below:

MyModel.objects.first()
MyModel.objects.all().first()
MyModel.objects.all()[0]
MyModel.objects.filter().first()
MyModel.objects.filter()[0]

In addition, you can get the last object with these ways as shown below:

MyModel.objects.last()
MyModel.objects.all().last()
MyModel.objects.filter().last()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文