Skip to content

Commit 7679ae0

Browse files
committed
add unique creation/deletion support to SchemaEditor.alter_field()
1 parent 470a014 commit 7679ae0

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

django_mongodb/features.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
9090
# AlterField
9191
"schema.tests.SchemaTests.test_alter_auto_field_to_integer_field",
9292
"schema.tests.SchemaTests.test_alter_field_default_dropped",
93-
"schema.tests.SchemaTests.test_alter_field_fk_to_o2o",
94-
"schema.tests.SchemaTests.test_alter_field_o2o_to_fk",
9593
"schema.tests.SchemaTests.test_alter_null_to_not_null",
9694
"schema.tests.SchemaTests.test_alter_primary_key_the_same_name",
9795
"schema.tests.SchemaTests.test_autofield_to_o2o",
9896
"schema.tests.SchemaTests.test_remove_constraints_capital_letters",
99-
# AlterField (unique)
100-
"schema.tests.SchemaTests.test_indexes",
101-
"schema.tests.SchemaTests.test_unique",
10297
}
10398
# $bitAnd, #bitOr, and $bitXor are new in MongoDB 6.3.
10499
_django_test_expected_failures_bitwise = {

django_mongodb/schema.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ def _alter_field(
8686
new_db_params,
8787
strict=False,
8888
):
89+
# Has unique been removed?
90+
if old_field.unique and (
91+
not new_field.unique or self._field_became_primary_key(old_field, new_field)
92+
):
93+
# Find the unique constraint for this field
94+
meta_constraint_names = {constraint.name for constraint in model._meta.constraints}
95+
constraint_names = self._constraint_names(
96+
model,
97+
[old_field.column],
98+
unique=True,
99+
primary_key=False,
100+
exclude=meta_constraint_names,
101+
)
102+
if strict and len(constraint_names) != 1:
103+
raise ValueError(
104+
f"Found wrong number ({len(constraint_names)}) of unique "
105+
f"constraints for {model._meta.db_table}.{old_field.column}"
106+
)
107+
for constraint_name in constraint_names:
108+
constraint = UniqueConstraint(
109+
fields=[old_field.name],
110+
name=constraint_name,
111+
)
112+
self.remove_constraint(model, constraint)
89113
# Removed an index? (no strict check, as multiple indexes are possible)
90114
# Remove indexes if db_index switched to False or a unique constraint
91115
# will now be used in lieu of an index. The following lines from the
@@ -122,6 +146,25 @@ def _alter_field(
122146
self.connection.database[model._meta.db_table].update_many(
123147
{}, {"$rename": {old_field.column: new_field.column}}
124148
)
149+
# Rename index
150+
if old_field.db_index and new_field.db_index:
151+
pass
152+
# Rename unique
153+
if old_field.unique and new_field.unique:
154+
old_constraint = UniqueConstraint(
155+
fields=[old_field.name], name=f"{model._meta.db_table}_{old_field.column}_key"
156+
)
157+
self.add_constraint(model, old_constraint)
158+
new_constraint = UniqueConstraint(
159+
fields=[new_field.name], name=f"{model._meta.db_table}_{new_field.column}_key"
160+
)
161+
self.add_constraint(model, new_constraint, field=new_field)
162+
# Added a unique?
163+
if self._unique_should_be_added(old_field, new_field):
164+
constraint = UniqueConstraint(
165+
fields=[new_field.name], name=f"{model._meta.db_table}_{new_field.column}_key"
166+
)
167+
self.add_constraint(model, constraint)
125168
# Added an index? Add an index if db_index switched to True or a unique
126169
# constraint will no longer be used in lieu of an index. The following
127170
# lines from the truth table show all True cases; the rest are False:

0 commit comments

Comments
 (0)