查看 ID,似乎当您将条目分配给变量时,您得到的是它的副本,而不是它的原始引用:
In [11]: people = People.objects.filter(salary=100)
In [12]: person = people[0]
In [13]: person.salary = 5000
In [14]: print person.salary
5000
In [15]: people[0].salary
Out[15]: 100
In [16]: id(people[0])
Out[16]: 35312400
In [17]: id(person)
Out[17]: 35313104
那么,让我们深入看看它发生了什么。您知道在 Django 中,查询集仅在您需要它们的结果时才被评估(惰性评估)。引用Django 文档:
切片。如限制查询集中所述,可以使用 Python 的数组切片语法对查询集进行切片。对未计算的 QuerySet 进行切片通常会返回另一个未计算的 QuerySet,但如果您使用切片语法的“step”参数,Django 将执行数据库查询,并返回一个列表。对已评估(部分或全部)的 QuerySet 进行切片也会返回一个列表。
特别是查看'django.db.models.query' 源代码,
def __getitem__(self, k):
"""
Retrieves an item or slice from the set of results.
"""
# some stuff here ...
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 k.step and list(qs)[::k.step] or qs
qs = self._clone()
qs.query.set_limits(k, k + 1)
return list(qs)[0]
您可以看到,当您使用slicing时,您正在调用该__getitem__
方法。然后该self._clone
方法将为您提供同一 QuerySet 的不同实例。这就是你得到不同结果的原因。