我有以下简单的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'
,明明在update_names()
中已经更新为'OPEN'
了?
奇怪的是,如果我用m2.update_names(name='OPEN', other_a_list=[m2,m3])
替换m2.update_names(name='OPEN', other_a_list=related_a_instances)
,所有断言都通过了。这是怎么回事?我难住了!
因为您没有从数据库中刷新m3。related_a_instances
从数据库中获取全新的对象;即使这些条目引用了与m1到m3相同的db行,它们也不是相同的对象,对其中一个的更新不会影响另一个。
如果您在断言之前执行了m3 = MyClassA.objects.get(pk=m3)
,您将看到更改。
你的替代方法通过的原因是你的是发送相同的对象m3给更新方法。