Django对象改变模型字段

时间:2009-05-26 11:44:43

标签: python django django-models

这不起作用:

>>> 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)

并改变缺口。

为什么会这样。

3 个答案:

答案 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实例(尽管其中包含所有相同的数据)。