2009-05-26 53 views
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) 

,并更改昵称它的工作原理。

为什么如此。

回答

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]再次查询块中的一个返回Person对象的另一个实例,说PersonObject2例如。这将保持不变!所以它等价于调用类似于:

PersonObject2.save() 

但是这与PersonObject1无关。

+0

很好解释!谢谢! – 2009-05-27 17:08:44

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 
+0

+1很好的答案,非常丰富的信息(特别是最后一部分......) – 2009-05-26 12:11:27

+3

提及all()是一个QuerySet,而不是一个实际的列表将是有益的。 http://docs.djangoproject.com/zh/dev/topics/db/queries/#retrieving-all-objects – 2009-05-26 12:34:32

+0

感谢您指出它 – kender 2009-05-26 12:37:01

2

Person.objects.all()返回一个QuerySet,这是懒惰的(直到请求数据时才执行数据库查询)。切片QuerySet(pa [2])执行数据库查询以从数据库中获取单个行(使用SQL中的LIMIT和OFFSET)。再次切片QuerySet不会再次执行数据库查询(结果被缓存),但它确实会返回模型的新实例。每次访问pa [2]时,都会得到一个新的Person实例(虽然其中包含所有相同的数据)。