这一定非常简单,但我无法理解它。 我想为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'
为什么无法识别保存属性或提供任何错误消息?
答案 0 :(得分:4)
我相信Bibhas的答案大部分都是正确的。您始终通过QuerySet引用数据的事实Profile.objects.all()
是其中最大的部分。再加上Django处理切片的方式(比如列表索引,但是QuerySet实际上并不是一个列表),以及数据库不必考虑订购记录的事实,你有一个很棒的来源困惑和沮丧。
序列
a = Profile.objects.all()
a[1].status
将产生类似于此的SQL:
SELECT * FROM user_profile LIMIT 1 OFFSET 1;
以获取表中的单个值。这里有几个重要的事情:
我知道MySQL,通常会按照最近更新的顺序返回记录。因此,只需保存记录,就不可能像以前一样处于同一位置。它可能会移动到结果集的开头或结尾,但不太可能保留在位置1(返回的第二个项目)。
为避免这种情况,请不要将查询集视为列表。不要使用切片语法直接对您检索到的项目执行操作。如果需要这样做,则将它们存储在临时变量中,并对该变量执行所有操作。
这个小修改可以避免所有麻烦:
>>> a = Profile.objects.all()
>>> b = a[1]
>>> b.status
'U'
>>> b.status = 'C'
>>> b.save()
>>> b.status
'C'
或者,如果您需要将其视为列表,则将其设为一个。从QuerySet中创建一个列表将完全评估它,并将整个结果集存储在内存中,每次请求时,[1]保证是同一个对象。
>>> a = list(Profile.objects.all()) # Warning -- may be huge if the Profile table is large
>>> a[1].status
'U'
>>> a[1].status = 'C'
>>> a[1].save()
>>> a[1].status
'C'
答案 1 :(得分:3)
看看这个 -
>>> from apps.users.models import Member
>>> members = Member.objects.all()
>>> members[1].user_type
u'C'
>>> members[1].user_type = 'M'
>>> members[1].save()
>>> members[1].user_type
u'C'
>>> m = members[1]
>>> m.user_type
u'C'
>>> m.user_type = 'M'
>>> m.save()
>>> m.user_type
'M'
这是我认为正在发生的事情:all()
方法返回一个QuerySet。从上面的查询中,当您对QuerySet中的项执行save()
时,更改不会提交到数据库。但是如果你单独在Member
对象上执行它,它确实有效。并从Django文档 -
QuerySets是懒惰的 - 创建QuerySet的行为不涉及 任何数据库活动。你可以整天堆叠过滤器, 在QuerySet之前,Django实际上不会运行查询 评估。 ......
通常,不从数据库中获取QuerySet的结果 直到你“问”他们。执行此操作时,将按以下方式评估QuerySet 访问数据库。
您可以阅读更多here。因此save()
上的members[1]
方法不会触及数据库或从那里读回。虽然Member
对象的更改已提交到数据库并立即回读。
答案 2 :(得分:0)
PROFILE_STATUS[0]
将返回('C', 'Claimed')
及其元组。您需要PROFILE_STATUS[0][0]
:
a[1].status = Profile.PROFILE_STATUS[0][0]