Opened 10 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)

24860-test.diff (3.8 KB ) - added by Tim Graham 9 years ago.

Download all attachments as: .zip

Change History (3)

comment:1 by Tim Graham, 9 years ago

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?

by Tim Graham, 9 years ago

Attachment: 24860-test.diff added

comment:2 by Tim Graham, 9 years ago

Resolution: needsinfo
Status: newclosed
Note: See TracTickets for help on using tickets.
Back to Top