When a field has both unique=True AND participates in a unique_together constraint, altering that field (e.g., changing its type or nullability) causes the unique_together constraint to be dropped but not restored. Only the single-field unique constraint is restored.
In mssql/schema.py, the _alter_field method's restoration logic for unique_together is inside an else block that only executes when the field does NOT have unique=True.
Steps to Reproduce
- Create a model with:
- Field
a with unique=True
- Field
b
unique_together = (('a', 'b'),) in Meta
class MyModel(models.Model):
a = models.CharField(max_length=20, unique=True)
b = models.CharField(max_length=20)
class Meta:
unique_together = (('a', 'b'),)
- Create a migration that alters field
a (e.g., changes max_length):
operations = [
migrations.AlterField(
model_name='mymodel',
name='a',
field=models.CharField(max_length=40, unique=True), # changed from max_length=20
),
]
- Run the migration
- Check database constraints using introspection or SQL Server Management Studio
Expected Behavior
After altering field a, both constraints should exist in the database:
- Single-field unique constraint on column
a
- Multi-field unique constraint on columns
(a, b) from unique_together
Actual Behavior
Only the single-field unique constraint on a is restored. The unique_together constraint on (a, b) is lost permanently.
Django Versions Affected
All supported versions
When a field has both
unique=TrueAND participates in aunique_togetherconstraint, altering that field (e.g., changing its type or nullability) causes theunique_togetherconstraint to be dropped but not restored. Only the single-field unique constraint is restored.In
mssql/schema.py, the_alter_fieldmethod's restoration logic forunique_togetheris inside anelseblock that only executes when the field does NOT haveunique=True.Steps to Reproduce
awithunique=Truebunique_together = (('a', 'b'),)in Metaa(e.g., changesmax_length):Expected Behavior
After altering field
a, both constraints should exist in the database:a(a, b)fromunique_togetherActual Behavior
Only the single-field unique constraint on
ais restored. Theunique_togetherconstraint on(a, b)is lost permanently.Django Versions Affected
All supported versions