Why is Django reporting inconsistent values for this instance attribute?
<p>I have the following simple Django model class:</p>

<pre><code>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"]
</code></pre>

<p>When I run the following code it, the last assertion fails:</p>

<pre><code>    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"
</code></pre>

<p>Here is the console output when the failure happens:</p>

<pre><code>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
</code></pre>

<p>Why does the calling function think <code>m3.status</code> is <code>'CREATED'</code> when clearly it was updated to <code>'OPEN'</code> in the <code>update_names()</code>? </p>

<p>Weirdly, if I replace <code>m2.update_names(name='OPEN', other_a_list=related_a_instances)</code> with <code>m2.update_names(name='OPEN', other_a_list=[m2,m3])</code>, all assertions pass. What's going on here? I'm stumped!</p>

<p>Because you haven't refreshed m3 from the database. <code>related_a_instances</code> fetches brand new objects from the database; even though those items refer to the same db rows as m1 to m3, they are not the same objects and updates to one do not affect the other.</p>

<p>If you did <code>m3 = MyClassA.objects.get(pk=m3)</code> before your assertion, you would see the change.</p>

<p>The reason your alternative method passes is that then you <em>are</em> sending the same object, m3, to the update method.</p>

python django django-models django-queryset