这一定很简单,但我就是想不明白。我想给一个django模型示例赋一个简单的一个字符的值。我已经做了一百万次了,但在这个例子中,它不起作用。
my models.py
class MetaInformation(models.Model):
# part of the class profile ...
PROFILE_STATUS = (
('C', 'Claimed'),
('U', 'Unclaimed'),)
status = models.CharField(_('Profile'), max_length=1,
choices = PROFILE_STATUS,)
class Profile(MetaInformation):
# additional attributes
...
现在我在Django shell
中执行:
In [1]: a = Profile.objects.all()
In [2]: a[1].status
Out[2]: u'U'
In [3]: a[1].status = Profile.PROFILE_STATUS[0] # equal to 'C'
In [4]: a[1].save()
我希望结果是
In [14]: a[1].status
Out[14]: u'C'
但 Django 回来了
In [14]: a[1].status
Out[14]: u'U'
- 为什么保存属性时无法识别或出现任何错误消息?**
3条答案
按热度按时间lvjbypge1#
我相信Bibhas有大部分正确的答案。事实上,你总是通过一个QuerySet引用数据,
Profile.objects.all()
是最大的部分。再加上Django处理切片的方式(像列表索引,但QuerySet不是真正的列表),以及数据库不必考虑记录的顺序,这是一个令人困惑和沮丧的奇妙来源。序列
将生成类似于以下内容的SQL:
才能从表中得到一个值。这里有几个重要的东西:
1.只提取一条记录。这样做是为了提高效率,因为您只请求了一条记录,所以没有必要再检索任何记录。这也意味着
1.此查询没有指定顺序。数据库可以按最有效的顺序返回行,并且该顺序甚至可以在查询之间更改。
我知道MySQL通常会按照最近更新的顺序返回记录,所以仅仅保存记录,它就不太可能位于与之前相同的位置,它可能会移动到结果集的开头或结尾,但不太可能停留在位置1(返回的第二项)。
为了避免这种情况,不要把查询集当作一个列表,不要直接对使用切片语法检索到的项执行操作,如果需要这样做,那么将它们存储在一个临时变量中,并对该变量执行所有操作。
这个小小的修改就可以避免所有的麻烦:
或者,如果你需要把它当作一个列表来处理,那就把它变成一个列表。从QuerySet中生成一个列表将完全计算它,并将整个结果集存储在内存中,其中的[1]保证在你每次请求它时都是同一个对象。
dfty9e192#
你看看这个-
以下是我认为正在发生的事情:
all()
方法返回一个QuerySet。从上面的查询中可以看出,当你对QuerySet中的一个项目执行save()
时,更改不会被提交到数据库。但是如果你对Member
对象单独执行,它会起作用。从Django文档中可以看出-QuerySet是懒惰的--创建QuerySet的行为不涉及任何数据库活动。您可以整天将过滤器堆叠在一起,Django在计算QuerySet之前不会真正运行查询。
一般来说,QuerySet的结果只有在你“请求”它们的时候才会从数据库中获取,当你请求的时候,QuerySet会通过访问数据库来计算。
你可以在这里读到更多的内容。所以
members[1]
上的save()
方法不接触数据库或从那里读回。而Member
对象上的更改被提交到数据库并立即读回。p8ekf7hl3#
PROFILE_STATUS[0]
将返回('C', 'Claimed')
和它的一个元组,你需要PROFILE_STATUS[0][0]
: