#24860: Migrations leak stale RelatedManager related_model definitions
------------------------------+---------------------------------------
Reporter: ecederstrand | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 1.8
Severity: Normal | Keywords: migration, RelatedManager
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+---------------------------------------
I have a Django 1.8.2 app with models A and B, where data in class A has
been migrated from one field to another. My actual code is a lot more
involved and difficult to reduce to a sane test case, but the following is
the essence of my debugging:
{{{
# Unchanged
class B(models.Model):
pass
# version 1
class A(models.Model):
b = models.ForeignKey(B)
x = models.FooField()
}}}
Now field 'y' is added to class A and a migration is created
{{{
# version 2
class A(models.Model):
rel = models.ForeignKey(B)
x = models.FooField()
y = models.BarField()
}}}
A data migration to move data from 'x' to 'y' is created
{{{
A = apps.get_model("my_app", "A")
for i in A.objects.all():
i.y = i.x
i.save()
}}}
Field 'x' is no longer needed on class A. New migration is created
{{{
# version 3
class A(models.Model):
rel = models.ForeignKey(B)
y = models.BarField()
}}}
Now when I run a test case which uses prefetch, invalid SQL is generated.
{{{
def test_case():
list(B.objects.all().prefetch_related('a_set'))
-> psycopg2.ProgrammingError: column A.x does not exist
}}}
The reason for this is that 'def related_manager_cls()' in
django/db/models/fields/related.py:832 is a @cached_property. When I run
my test case, the migrations are run to create the test database. This
caches version 2 of class A in self.related.related_model as a <class
'__fake__.A'>, which is then returned later on in the test case. Thus,
prefetch SQL for version 2 is produced instead of for version 3. I suspect
the problem occurs because of the data migration.
No errors show when I use prefetch_related() in production, because the
migrations aren't run.
I'm uncertain how to fix this. Somehow the property caches should be
invalidated after each migration is run.
It seems related.py has more potentally dangerous uses of @cached_property
--
Ticket URL: <https://code.djangoproject.com/ticket/24860>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/055.12f4b19126f96b2e0834db942da1eab3%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.