gpt4 book ai didi

python - 为什么 queryset[0] 和 queryset.first() 返回不同的记录?

转载 作者:行者123 更新时间:2023-12-04 13:15:54 26 4
gpt4 key购买 nike

我今天发现我可以通过索引引用它们来访问查询集中的元素,即 queryset[n] .然而,紧接着我发现queryset[0]不返回与 queryset.first() 相同的记录.为什么会这样,并且是更“正确”的其中之一? (我知道 .first() 更快,但除此之外)

python 3.7.4
Django 1.11.20

最佳答案

qs[0] 之间存在小的语义差异和 qs.first() .如果您自己没有在查询集中指定顺序,那么 Django 将在获取第一个元素之前按主键对查询集本身进行排序。

此外.first()将返回 None如果查询集为空。而qs[0]将引发 IndexError .

声称.first()更快但不是True .事实上,如果你使用 qs[n] ,然后 Django 会在幕后通过 qs[n:n+1] 切片来获取记录。 ,因此,鉴于数据库后端支持此功能,它将使用 LIMIT 1 OFFSET n 进行查询,从而获取一条记录,就像 .first()会做。如果查询集已经被检索,它也不会进行额外的查询,因为数据已经被缓存了。

你可以在 GitHub 上看到实现:

    def first(self):
"""
Returns the first object of a query, returns None if no match is found.
"""
objects = list((self if self.ordered else self.order_by('pk'))[:1])
if objects:
return objects[0]
return None


如您所见,如果查询集已经排序( self.orderedTrue ,那么我们取 self[:1] ,检查是否有记录,如果有则返回。如果没有,我们返回 None

在特定索引处检索项目的代码更加神秘。它基本上将从 k 设置限制至 k+1 ,具体化该项目,并返回第一个项目,正如我们在 source code [GitHub] 中看到的那样:

    def __getitem__(self, k):
"""
Retrieves an item or slice from the set of results.
"""
if not isinstance(k, (slice,) + six.integer_types):
raise TypeError
assert ((not isinstance(k, slice) and (k >= 0)) or
(isinstance(k, slice) and (k.start is None or k.start >= 0) and
(k.stop is None or k.stop >= 0))), \
"Negative indexing is not supported."

if self._result_cache is not None:
return self._result_cache[k]

if isinstance(k, slice):
qs = self._clone()
if k.start is not None:
start = int(k.start)
else:
start = None
if k.stop is not None:
stop = int(k.stop)
else:
stop = None
qs.query.set_limits(start, stop)
return list(qs)[::k.step] if k.step else qs

qs = self._clone()
qs.query.set_limits(k, k + 1)
return list(qs)[0]

关于python - 为什么 queryset[0] 和 queryset.first() 返回不同的记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60553723/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com