11from django .db .backends .base .schema import BaseDatabaseSchemaEditor
2- from django .db .models import Index
2+ from django .db .models import Index , UniqueConstraint
33from pymongo .operations import IndexModel
44
55
@@ -14,8 +14,8 @@ def create_model(self, model):
1414
1515 def _create_model_indexes (self , model ):
1616 """
17- Create all indexes (field indexes, index_together, Meta.indexes) for
18- the specified model.
17+ Create all indexes (field indexes & uniques , index_together,
18+ Meta.constraints, Meta.indexes) for the specified model.
1919 """
2020 if not model ._meta .managed or model ._meta .proxy or model ._meta .swapped :
2121 return
@@ -25,11 +25,19 @@ def _create_model_indexes(self, model):
2525 index = Index (fields = [field .name ])
2626 index .set_name_with_model (model )
2727 self .add_index (model , index )
28+ # Field uniques
29+ for field in model ._meta .local_fields :
30+ if field .unique and field .column != "_id" :
31+ constraint = UniqueConstraint (fields = [field .name ], name = "%s_uniq" % field .column )
32+ self .add_constraint (model , constraint )
2833 # Meta.index_together (RemovedInDjango51Warning)
2934 for field_names in model ._meta .index_together :
3035 index = Index (fields = field_names )
3136 index .set_name_with_model (model )
3237 self .add_index (model , index )
38+ # Meta.constraints
39+ for constraint in model ._meta .constraints :
40+ self .add_constraint (model , constraint )
3341 # Meta.indexes
3442 for index in model ._meta .indexes :
3543 self .add_index (model , index )
@@ -95,15 +103,23 @@ def alter_index_together(self, model, old_index_together, new_index_together):
95103 def alter_unique_together (self , model , old_unique_together , new_unique_together ):
96104 pass
97105
98- def add_index (self , model , index ):
106+ def add_index (self , model , index , unique = False ):
99107 if index .contains_expressions :
100108 return
109+ kwargs = {}
110+ if unique :
111+ filter_expression = {}
112+ for field_name , _ in index .fields_orders :
113+ field = model ._meta .get_field (field_name )
114+ filter_expression [field_name ] = {"$type" : field .db_type (self .connection )}
115+ kwargs = {"partialFilterExpression" : filter_expression , "unique" : True }
101116 idx = IndexModel (
102117 [
103118 (model ._meta .get_field (field_name ).column , 1 if order == "" else - 1 )
104119 for field_name , order in index .fields_orders
105120 ],
106121 name = index .name ,
122+ ** kwargs ,
107123 )
108124 self .connection .database [model ._meta .db_table ].create_indexes ([idx ])
109125
@@ -113,10 +129,26 @@ def remove_index(self, model, index):
113129 self .connection .database [model ._meta .db_table ].drop_index (index .name )
114130
115131 def add_constraint (self , model , constraint ):
116- pass
132+ if isinstance (constraint , UniqueConstraint ) and self ._unique_supported (
133+ condition = constraint .condition ,
134+ deferrable = constraint .deferrable ,
135+ include = constraint .include ,
136+ expressions = constraint .expressions ,
137+ nulls_distinct = constraint .nulls_distinct ,
138+ ):
139+ idx = Index (fields = constraint .fields , name = constraint .name )
140+ self .add_index (model , idx , unique = True )
117141
118142 def remove_constraint (self , model , constraint ):
119- pass
143+ if isinstance (constraint , UniqueConstraint ) and self ._unique_supported (
144+ condition = constraint .condition ,
145+ deferrable = constraint .deferrable ,
146+ include = constraint .include ,
147+ expressions = constraint .expressions ,
148+ nulls_distinct = constraint .nulls_distinct ,
149+ ):
150+ idx = Index (fields = constraint .fields , name = constraint .name )
151+ self .remove_index (model , idx )
120152
121153 def alter_db_table (self , model , old_db_table , new_db_table ):
122154 if old_db_table == new_db_table :
0 commit comments