Opened 9 years ago
Closed 9 years ago
#24860 closed Bug (needsinfo)
Migrations leak stale RelatedManager related_model definitions
Reported by: | Erik Cederstrand | Owned by: | nobody |
---|---|---|---|
Component: | Migrations | Version: | 1.8 |
Severity: | Normal | Keywords: | migration, RelatedManager |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
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
Attachments (1)
Change History (3)
comment:1 by , 9 years ago
by , 9 years ago
Attachment: | 24860-test.diff added |
---|
comment:2 by , 9 years ago
Resolution: | → needsinfo |
---|---|
Status: | new → closed |
I tried to reproduce with a test based on the steps you outlined, but didn't have any luck (also tried similar steps in a sample project). Could you try tweaking the test until it fails or submit a sample project that reproduces the crash?