diff --git a/django/db/migrations/operations/models.py b/django/db/migrations/operations/models.py index 38c68f3ff3..34b14107a7 100644 --- a/django/db/migrations/operations/models.py +++ b/django/db/migrations/operations/models.py @@ -342,6 +342,40 @@ class CreateModel(ModelOperation): managers=self.managers, ), ] + elif isinstance(operation, AddConstraint): + return [ + CreateModel( + self.name, + fields=self.fields, + options={ + **self.options, + "constraints": [ + *self.options.get("constraints", []), + operation.constraint, + ], + }, + bases=self.bases, + managers=self.managers, + ), + ] + elif isinstance(operation, RemoveConstraint): + options_constraints = [ + constraint + for constraint in self.options.get("constraints", []) + if constraint.name != operation.name + ] + return [ + CreateModel( + self.name, + fields=self.fields, + options={ + **self.options, + "constraints": options_constraints, + }, + bases=self.bases, + managers=self.managers, + ), + ] return super().reduce(operation, app_label) diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index 340805b259..d36b72907d 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -2762,21 +2762,23 @@ class AutodetectorTests(BaseAutodetectorTests): }, ) changes = self.get_changes([], [author]) - added_constraint = models.CheckConstraint( + constraint = models.CheckConstraint( check=models.Q(name__contains="Bob"), name="name_contains_bob" ) # Right number of migrations? self.assertEqual(len(changes["otherapp"]), 1) # Right number of actions? migration = changes["otherapp"][0] - self.assertEqual(len(migration.operations), 2) + self.assertEqual(len(migration.operations), 1) # Right actions order? - self.assertOperationTypes( - changes, "otherapp", 0, ["CreateModel", "AddConstraint"] - ) - self.assertOperationAttributes(changes, "otherapp", 0, 0, name="Author") + self.assertOperationTypes(changes, "otherapp", 0, ["CreateModel"]) self.assertOperationAttributes( - changes, "otherapp", 0, 1, model_name="author", constraint=added_constraint + changes, + "otherapp", + 0, + 0, + name="Author", + options={"constraints": [constraint]}, ) def test_add_constraints(self): @@ -4177,7 +4179,7 @@ class AutodetectorTests(BaseAutodetectorTests): changes, "testapp", 0, - ["CreateModel", "AddConstraint"], + ["CreateModel"], ) self.assertOperationAttributes( changes, @@ -4185,7 +4187,14 @@ class AutodetectorTests(BaseAutodetectorTests): 0, 0, name="Author", - options={"order_with_respect_to": "book"}, + options={ + "order_with_respect_to": "book", + "constraints": [ + models.CheckConstraint( + check=models.Q(_order__gt=1), name="book_order_gt_1" + ) + ], + }, ) def test_add_model_order_with_respect_to_index(self): diff --git a/tests/migrations/test_optimizer.py b/tests/migrations/test_optimizer.py index ece6580ad8..5c1fe3020e 100644 --- a/tests/migrations/test_optimizer.py +++ b/tests/migrations/test_optimizer.py @@ -1326,3 +1326,66 @@ class OptimizerTests(SimpleTestCase): ), ], ) + + def test_create_model_add_constraint(self): + gt_constraint = models.CheckConstraint( + check=models.Q(weight__gt=0), name="pony_weight_gt_0" + ) + self.assertOptimizesTo( + [ + migrations.CreateModel( + name="Pony", + fields=[ + ("weight", models.IntegerField()), + ], + ), + migrations.AddConstraint("Pony", gt_constraint), + ], + [ + migrations.CreateModel( + name="Pony", + fields=[ + ("weight", models.IntegerField()), + ], + options={"constraints": [gt_constraint]}, + ), + ], + ) + + def test_create_model_remove_constraint(self): + self.assertOptimizesTo( + [ + migrations.CreateModel( + name="Pony", + fields=[ + ("weight", models.IntegerField()), + ], + options={ + "constraints": [ + models.CheckConstraint( + check=models.Q(weight__gt=0), name="pony_weight_gt_0" + ), + models.UniqueConstraint( + "weight", name="pony_weight_unique" + ), + ], + }, + ), + migrations.RemoveConstraint("Pony", "pony_weight_gt_0"), + ], + [ + migrations.CreateModel( + name="Pony", + fields=[ + ("weight", models.IntegerField()), + ], + options={ + "constraints": [ + models.UniqueConstraint( + "weight", name="pony_weight_unique" + ), + ] + }, + ), + ], + )