这不起作用:Django的对象更改模型场
>>> 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)
,并更改昵称它的工作原理。
为什么如此。
这不起作用:Django的对象更改模型场
>>> 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)
,并更改昵称它的工作原理。
为什么如此。
>>> 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]再次查询块中的一个返回Person对象的另一个实例,说PersonObject2例如。这将保持不变!所以它等价于调用类似于:
PersonObject2.save()
但是这与PersonObject1无关。
如果您分配您的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
+1很好的答案,非常丰富的信息(特别是最后一部分......) – 2009-05-26 12:11:27
提及all()是一个QuerySet,而不是一个实际的列表将是有益的。 http://docs.djangoproject.com/zh/dev/topics/db/queries/#retrieving-all-objects – 2009-05-26 12:34:32
感谢您指出它 – kender 2009-05-26 12:37:01
Person.objects.all()
返回一个QuerySet
,这是懒惰的(直到请求数据时才执行数据库查询)。切片QuerySet
(pa [2])执行数据库查询以从数据库中获取单个行(使用SQL中的LIMIT和OFFSET)。再次切片QuerySet
不会再次执行数据库查询(结果被缓存),但它确实会返回模型的新实例。每次访问pa [2]时,都会得到一个新的Person实例(虽然其中包含所有相同的数据)。
很好解释!谢谢! – 2009-05-27 17:08:44