[1.8.x] Fixed #24435 -- Prevented m2m field removal and addition in migrations when changing blank
Thanks Mark Tranchant for the report and Tim Graham for the test and
review.
Backport of a9e29fae10
from master
This commit is contained in:
parent
44dd65fb2c
commit
bff446c205
|
@ -848,8 +848,16 @@ class MigrationAutodetector(object):
|
|||
old_field_dec = self.deep_deconstruct(old_field)
|
||||
new_field_dec = self.deep_deconstruct(new_field)
|
||||
if old_field_dec != new_field_dec:
|
||||
if (not isinstance(old_field, models.ManyToManyField) and
|
||||
not isinstance(new_field, models.ManyToManyField)):
|
||||
both_m2m = (
|
||||
isinstance(old_field, models.ManyToManyField) and
|
||||
isinstance(new_field, models.ManyToManyField)
|
||||
)
|
||||
neither_m2m = (
|
||||
not isinstance(old_field, models.ManyToManyField) and
|
||||
not isinstance(new_field, models.ManyToManyField)
|
||||
)
|
||||
if both_m2m or neither_m2m:
|
||||
# Either both fields are m2m or neither is
|
||||
preserve_default = True
|
||||
if (old_field.null and not new_field.null and not new_field.has_default() and
|
||||
not isinstance(new_field, models.ManyToManyField)):
|
||||
|
@ -870,6 +878,7 @@ class MigrationAutodetector(object):
|
|||
)
|
||||
)
|
||||
else:
|
||||
# We cannot alter between m2m and concrete fields
|
||||
self._generate_removed_field(app_label, model_name, field_name)
|
||||
self._generate_added_field(app_label, model_name, field_name)
|
||||
|
||||
|
|
|
@ -127,6 +127,10 @@ class AutodetectorTests(TestCase):
|
|||
("id", models.AutoField(primary_key=True)),
|
||||
("publishers", models.ManyToManyField("testapp.Publisher")),
|
||||
])
|
||||
author_with_m2m_blank = ModelState("testapp", "Author", [
|
||||
("id", models.AutoField(primary_key=True)),
|
||||
("publishers", models.ManyToManyField("testapp.Publisher", blank=True)),
|
||||
])
|
||||
author_with_m2m_through = ModelState("testapp", "Author", [
|
||||
("id", models.AutoField(primary_key=True)),
|
||||
("publishers", models.ManyToManyField("testapp.Publisher", through="testapp.Contract")),
|
||||
|
@ -1263,6 +1267,16 @@ class AutodetectorTests(TestCase):
|
|||
self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
|
||||
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="publishers")
|
||||
|
||||
def test_alter_many_to_many(self):
|
||||
before = self.make_project_state([self.author_with_m2m, self.publisher])
|
||||
after = self.make_project_state([self.author_with_m2m_blank, self.publisher])
|
||||
autodetector = MigrationAutodetector(before, after)
|
||||
changes = autodetector._detect_changes()
|
||||
# Right number/type of migrations?
|
||||
self.assertNumberMigrations(changes, 'testapp', 1)
|
||||
self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
|
||||
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="publishers")
|
||||
|
||||
def test_create_with_through_model(self):
|
||||
"""
|
||||
Adding a m2m with a through model and the models that use it should be
|
||||
|
|
Loading…
Reference in New Issue