Skip to content

Commit 65c0476

Browse files
committed
add index creation/deletion support to SchemaEditor.alter_field()
1 parent 81ea2fd commit 65c0476

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

django_mongodb/features.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,12 @@ class DatabaseFeatures(BaseDatabaseFeatures):
7272
# AddField
7373
"schema.tests.SchemaTests.test_add_unique_charfield",
7474
# AlterField
75-
"schema.tests.SchemaTests.test_alter_field_add_index_to_integerfield",
7675
"schema.tests.SchemaTests.test_alter_field_fk_to_o2o",
7776
"schema.tests.SchemaTests.test_alter_field_o2o_keeps_unique",
7877
"schema.tests.SchemaTests.test_alter_field_o2o_to_fk",
7978
"schema.tests.SchemaTests.test_alter_int_pk_to_int_unique",
80-
# AlterField (db_index)
81-
"schema.tests.SchemaTests.test_alter_renames_index",
82-
"schema.tests.SchemaTests.test_indexes",
83-
"schema.tests.SchemaTests.test_remove_db_index_doesnt_remove_custom_indexes",
8479
# AlterField (unique)
80+
"schema.tests.SchemaTests.test_indexes",
8581
"schema.tests.SchemaTests.test_unique",
8682
"schema.tests.SchemaTests.test_unique_and_reverse_m2m",
8783
# alter_unique_together

django_mongodb/schema.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,27 @@ def _alter_field(
6666
strict=False,
6767
):
6868
collection = self.connection.database[model._meta.db_table]
69+
# Removed an index?
70+
old_field_indexed = self._field_should_be_indexed(model, old_field)
71+
new_field_indexed = self._field_should_be_indexed(model, new_field)
72+
if old_field_indexed and not new_field_indexed:
73+
self._remove_field_index(model, old_field)
6974
# Have they renamed the column?
7075
if old_field.column != new_field.column:
7176
collection.update_many({}, {"$rename": {old_field.column: new_field.column}})
77+
# Move index to the new field, if needed.
78+
if old_field_indexed and new_field_indexed:
79+
self._remove_field_index(model, old_field)
80+
self._add_field_index(model, new_field)
7281
# Replace NULL with the field default if the field and was changed from
7382
# NULL to NOT NULL.
7483
if new_field.has_default() and old_field.null and not new_field.null:
7584
column = new_field.column
7685
default = self.effective_default(new_field)
7786
collection.update_many({column: {"$eq": None}}, [{"$set": {column: default}}])
87+
# Added an index?
88+
if not old_field_indexed and new_field_indexed:
89+
self._add_field_index(model, new_field)
7890

7991
def remove_field(self, model, field):
8092
# Remove implicit M2M tables.
@@ -155,6 +167,27 @@ def _remove_composed_index(self, model, field_names, constraint_kwargs):
155167
collection = self.connection.database[model._meta.db_table]
156168
collection.drop_index(constraint_names[0])
157169

170+
def _remove_field_index(self, model, field):
171+
"""Remove a field's db_index=True index."""
172+
collection = self.connection.database[model._meta.db_table]
173+
meta_index_names = {index.name for index in model._meta.indexes}
174+
index_names = self._constraint_names(
175+
model,
176+
[field.column],
177+
index=True,
178+
# Retrieve only BTREE indexes since this is what's created with
179+
# db_index=True.
180+
type_=Index.suffix,
181+
exclude=meta_index_names,
182+
)
183+
if len(index_names) != 1:
184+
num_found = len(index_names)
185+
raise ValueError(
186+
f"Found wrong number ({num_found}) of constraints for "
187+
f"{model._meta.db_table}.{field.column}."
188+
)
189+
collection.drop_index(index_names[0])
190+
158191
def add_constraint(self, model, constraint):
159192
pass
160193

0 commit comments

Comments
 (0)