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)
并且换个昵称,就可以了。
这是为什么呢?
3 个回答
2
Person.objects.all()
这个命令会返回一个叫做 QuerySet
的东西,它是懒惰的,也就是说,直到你真正需要数据的时候,它才会去数据库查询。比如,当你用 pa[2]
这种方式切片 QuerySet
时,它会去数据库查询,拿到一行数据(在SQL中用的是LIMIT和OFFSET)。但是,如果你再次对同一个 QuerySet
进行切片,它就不会再去数据库查询了,因为结果已经被缓存了。不过,它会返回一个新的模型实例。每次你访问 pa[2]
时,实际上都是在获取一个新的 Person 实例(虽然里面的数据都是一样的)。
5
如果你把你的 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 的主键(PrimaryKey)是从 1 开始编号的,而不是从 0 开始,所以
Person.objects.all()[2] == Person.objects.get(pk=2)
False
Person.objects.all()[2] == Person.objects.get(pk=3)
True
11
>>> 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'>
数据库查询给你一个“人”的对象。
>>> pa[2]
数据库又查询一次,给你另一个“人”的对象。
>>> pa[2].first_name = "Blah"
我们把这个在内存中的实例叫做PersonObject1。它就像这样:
>>> PersonObject1.first_name = "Blah"
现在我们来做这个:
>>> pa[2].save()
pa[2]再次查询数据库,返回另一个“人”的对象,比如叫PersonObject2。这个对象不会改变!所以这就相当于调用类似于:
PersonObject2.save()
但是这和PersonObject1没有任何关系。