我有以下简单的Django模型类:
from django.db import models
class MyClassA(models.Model):
name = models.CharField(max_length=254)
parent_a = models.IntegerField()
def update_names(self, name, other_a_list):
a_set = set([self] + other_a_list)
for curr_a in a_set:
curr_a.name = name
curr_a.save()
print "Updated MyClassA #%s's name to %s" % (curr_a.pk, curr_a.name)
def related_a_instances(self):
family_list = MyClassA.objects.filter(parent_a=self.parent_a)
return [curr_a for curr_a in family_list if curr_a.name == "CREATED"]
当我运行以下代码时,最后一个断言失败:
m1 = MyClassA.objects.create(parent_a=99, name="OPEN",)
m2 = MyClassA.objects.create(parent_a=99, name="CREATED",)
assert m2.name == "CREATED"
m3 = MyClassA.objects.create(parent_a=99, name="CREATED",)
assert m3.name == "CREATED"
related_a_instances = m2.related_a_instances()
assert related_a_instances == [m2, m3]
m2.update_names(name="OPEN", other_a_list=related_a_instances)
print "Checking that MyClassA m1 (%s) is OPEN. My Code says its %s. DB says %s" % (m1.pk, m1.name, MyClassA.objects.get(pk=m1.pk).name)
assert m1.name == "OPEN"
print "Checking that MyClassA m2 (%s) is OPEN. My Code says its %s. DB says %s" % (m2.pk, m2.name, MyClassA.objects.get(pk=m2.pk).name)
assert m2.name == "OPEN"
print "Checking that MyClassA m3 (%s) is OPEN. My Code says its %s. DB says %s" % (m3.pk, m3.name, MyClassA.objects.get(pk=m3.pk).name)
assert m3.name == "OPEN"
以下是发生故障时的控制台输出:
Updated MyClassA #2's name to OPEN
Updated MyClassA #3's name to OPEN
Checking that MyClassA m1 (1) is OPEN. My Code says its OPEN. DB says OPEN
Checking that MyClassA m2 (2) is OPEN. My Code says its OPEN. DB says OPEN
Checking that MyClassA m3 (3) is OPEN. My Code says its CREATED. DB says OPEN
为什么调用函数在m3.status
明确更新为'CREATED'
时认为'OPEN'
为update_names()
?
奇怪的是,如果我用m2.update_names(name='OPEN', other_a_list=related_a_instances)
替换m2.update_names(name='OPEN', other_a_list=[m2,m3])
,则所有断言都会通过。这里发生了什么?我很难过!
答案 0 :(得分:2)
因为您还没有从数据库刷新m3。 related_a_instances
从数据库中获取全新的对象;即使这些项引用与m1到m3相同的db行,它们也不是同一个对象,对一个对象的更新不会影响另一个。
如果您在断言之前做过m3 = MyClassA.objects.get(pk=m3)
,您会看到更改。
您的替代方法通过的原因是您 将相同的对象m3发送到更新方法。