瀏覽代碼

Fixed #29000 -- Fixed RenameModel's renaming of a M2M column when run after RenameField.

Regression in 45ded053b1f4320284aa5dac63052f6d1baefea9.
Jeff 6 年之前
父節點
當前提交
fcc4e251db
共有 2 個文件被更改,包括 35 次插入6 次删除
  1. 7 6
      django/db/migrations/operations/fields.py
  2. 28 0
      tests/migrations/test_operations.py

+ 7 - 6
django/db/migrations/operations/fields.py

@@ -271,15 +271,10 @@ class RenameField(FieldOperation):
         # Rename the field
         fields = model_state.fields
         found = False
+        delay = True
         for index, (name, field) in enumerate(fields):
             if not found and name == self.old_name:
                 fields[index] = (self.new_name, field)
-                # Delay rendering of relationships if it's not a relational
-                # field and not referenced by a foreign key.
-                delay = (
-                    not field.is_relation and
-                    not is_referenced_by_foreign_key(state, self.model_name_lower, field, self.name)
-                )
                 found = True
             # Fix from_fields to refer to the new field.
             from_fields = getattr(field, 'from_fields', None)
@@ -288,6 +283,12 @@ class RenameField(FieldOperation):
                     self.new_name if from_field_name == self.old_name else from_field_name
                     for from_field_name in from_fields
                 ])
+            # Delay rendering of relationships if it's not a relational
+            # field and not referenced by a foreign key.
+            delay = delay and (
+                not field.is_relation and
+                not is_referenced_by_foreign_key(state, self.model_name_lower, field, self.name)
+            )
         if not found:
             raise FieldDoesNotExist(
                 "%s.%s has no field named '%s'" % (app_label, self.model_name, self.old_name)

+ 28 - 0
tests/migrations/test_operations.py

@@ -802,6 +802,34 @@ class OperationTests(OperationTestBase):
         self.assertEqual(PonyRider.objects.count(), 2)
         self.assertEqual(pony.riders.count(), 2)
 
+    def test_rename_m2m_model_after_rename_field(self):
+        """RenameModel renames a many-to-many column after a RenameField."""
+        app_label = 'test_rename_multiple'
+        project_state = self.apply_operations(app_label, ProjectState(), operations=[
+            migrations.CreateModel('Pony', fields=[
+                ('id', models.AutoField(primary_key=True)),
+                ('name', models.CharField(max_length=20)),
+            ]),
+            migrations.CreateModel('Rider', fields=[
+                ('id', models.AutoField(primary_key=True)),
+                ('pony', models.ForeignKey('test_rename_multiple.Pony', models.CASCADE)),
+            ]),
+            migrations.CreateModel('PonyRider', fields=[
+                ('id', models.AutoField(primary_key=True)),
+                ('riders', models.ManyToManyField('Rider')),
+            ]),
+            migrations.RenameField(model_name='pony', old_name='name', new_name='fancy_name'),
+            migrations.RenameModel(old_name='Rider', new_name='Jockey'),
+        ], atomic=connection.features.supports_atomic_references_rename)
+        Pony = project_state.apps.get_model(app_label, 'Pony')
+        Jockey = project_state.apps.get_model(app_label, 'Jockey')
+        PonyRider = project_state.apps.get_model(app_label, 'PonyRider')
+        # No "no such column" error means the column was renamed correctly.
+        pony = Pony.objects.create(fancy_name='a good name')
+        jockey = Jockey.objects.create(pony=pony)
+        ponyrider = PonyRider.objects.create()
+        ponyrider.riders.add(jockey)
+
     def test_add_field(self):
         """
         Tests the AddField operation.