11from django .db .backends .base .schema import BaseDatabaseSchemaEditor
2+ from django .db .models import Index
3+ from pymongo .operations import IndexModel
24
35from .query import wrap_database_errors
46
@@ -7,11 +9,30 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
79 @wrap_database_errors
810 def create_model (self , model ):
911 self .connection .database .create_collection (model ._meta .db_table )
12+ self ._create_model_indexes (model )
1013 # Make implicit M2M tables.
1114 for field in model ._meta .local_many_to_many :
1215 if field .remote_field .through ._meta .auto_created :
1316 self .create_model (field .remote_field .through )
1417
18+ def _create_model_indexes (self , model ):
19+ """
20+ Create all indexes (field indexes, index_together, Meta.indexes) for
21+ the specified model.
22+ """
23+ if not model ._meta .managed or model ._meta .proxy or model ._meta .swapped :
24+ return
25+ # Field indexes
26+ for field in model ._meta .local_fields :
27+ if self ._field_should_be_indexed (model , field ):
28+ self ._add_field_index (model , field )
29+ # Meta.index_together (RemovedInDjango51Warning)
30+ for field_names in model ._meta .index_together :
31+ self ._add_composed_index (model , field_names )
32+ # Meta.indexes
33+ for index in model ._meta .indexes :
34+ self .add_index (model , index )
35+
1536 def delete_model (self , model ):
1637 # Delete implicit M2m tables.
1738 for field in model ._meta .local_many_to_many :
@@ -29,6 +50,9 @@ def add_field(self, model, field):
2950 self .connection .database [model ._meta .db_table ].update_many (
3051 {}, [{"$set" : {column : self .effective_default (field )}}]
3152 )
53+ # Add an index, if required.
54+ if self ._field_should_be_indexed (model , field ):
55+ self ._add_field_index (model , field )
3256
3357 def _alter_field (
3458 self ,
@@ -60,21 +84,45 @@ def remove_field(self, model, field):
6084 # Unset field on existing documents.
6185 if column := field .column :
6286 self .connection .database [model ._meta .db_table ].update_many ({}, {"$unset" : {column : "" }})
87+ if self ._field_should_be_indexed (model , field ):
88+ self ._remove_field_index (model , field )
6389
6490 def alter_index_together (self , model , old_index_together , new_index_together ):
6591 pass
6692
6793 def alter_unique_together (self , model , old_unique_together , new_unique_together ):
6894 pass
6995
70- def add_index (self , model , index ):
71- pass
96+ def add_index (self , model , index , field = None ):
97+ if index .contains_expressions :
98+ return
99+ index_orders = (
100+ [(field .column , 1 )]
101+ if field
102+ else [
103+ (model ._meta .get_field (field_name ).column , 1 if order == "" else - 1 )
104+ for field_name , order in index .fields_orders
105+ ]
106+ )
107+ idx = IndexModel (index_orders , name = index .name )
108+ self .connection .database [model ._meta .db_table ].create_indexes ([idx ])
72109
73- def rename_index (self , model , old_index , new_index ):
74- pass
110+ def _add_composed_index (self , model , field_names ):
111+ """Add an index on the given list of field_names."""
112+ idx = Index (fields = field_names )
113+ idx .set_name_with_model (model )
114+ self .add_index (model , idx )
115+
116+ def _add_field_index (self , model , field ):
117+ """Add an index on a field with db_index=True."""
118+ index = Index (fields = [field .name ])
119+ index .name = self ._create_index_name (model ._meta .db_table , [field .column ])
120+ self .add_index (model , index , field = field )
75121
76122 def remove_index (self , model , index ):
77- pass
123+ if index .contains_expressions :
124+ return
125+ self .connection .database [model ._meta .db_table ].drop_index (index .name )
78126
79127 def add_constraint (self , model , constraint ):
80128 pass
0 commit comments