这不起作用:
>>> pa = Person.objects.all()
>>> pa[2].nickname
u'arst'
>>> pa[2].nickname = 'something else'
>>> pa[2].save()
>>> pa[2].nickname
u'arst'
但如果你采取
它就有效 p = Person.objects.get(pk=2)
并改变缺口。
为什么会这样。
答案 0 :(得分:10)
>>> type(Person.objects.all())
<class 'django.db.models.query.QuerySet'>
>>> pa = Person.objects.all() # Not evaluated yet - lazy
>>> type(pa)
<class 'django.db.models.query.QuerySet'>
DB查询给你一个Person对象
>>> pa[2]
DB再次查询给你另一个Person对象。
>>> pa[2].first_name = "Blah"
让我们调用驻留在内存中的此实例PersonObject1。所以它等同于这样:
>>> PersonObject1.first_name = "Blah"
现在让我们这样做:
>>> pa[2].save()
pa [2]再次查询db并返回person对象的另一个实例,例如PersonObject2。哪个会保持不变!所以它与调用类似的东西是等价的:
PersonObject2.save()
但这与PersonObject1无关。
答案 1 :(得分:4)
如果您将pa[2]
分配给变量,就像使用Person.objects.get(pk=2)
一样,那就是正确的:
pa = Person.objects.all()
print pa[2].nickname
'Jonny'
pa[2].nickname = 'Billy'
print pa[2].nickname
'Jonny'
# when you assign it to some variable, your operations
# change this particular object, not something that is queried out each time
p1 = pa[2]
print p1.nickname
'Jonny'
p1.nickname = 'Billy'
print p1.nickname
'Billy'
这与从数据库中提取对象的方法无关。
而且,顺便说一下,django将PrimaryKeys从1开始,而不是0,所以
Person.objects.all()[2] == Person.objects.get(pk=2)
False
Person.objects.all()[2] == Person.objects.get(pk=3)
True
答案 2 :(得分:2)
Person.objects.all()
返回一个QuerySet
,它是惰性的(在请求数据之前不会执行数据库查询)。切片QuerySet
(pa [2])执行数据库查询以从数据库中获取单行(在SQL中使用LIMIT和OFFSET)。再次切片QuerySet
不会再次执行数据库查询(结果被缓存),但它会返回模型的 new 实例。每次访问pa [2]时,您都会获得一个新的Person实例(尽管其中包含所有相同的数据)。