1
1
from django .db .backends .base .schema import BaseDatabaseSchemaEditor
2
- from django .db .models import Index
2
+ from django .db .models import Index , UniqueConstraint
3
3
from pymongo .operations import IndexModel
4
4
5
5
@@ -14,8 +14,8 @@ def create_model(self, model):
14
14
15
15
def _create_model_indexes (self , model ):
16
16
"""
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.
19
19
"""
20
20
if not model ._meta .managed or model ._meta .proxy or model ._meta .swapped :
21
21
return
@@ -25,11 +25,21 @@ def _create_model_indexes(self, model):
25
25
index = Index (fields = [field .name ])
26
26
index .name = self ._create_index_name (model ._meta .db_table , [field .column ])
27
27
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 (
32
+ fields = [field .name ], name = f"{ model ._meta .db_table } _{ field .column } _key"
33
+ )
34
+ self .add_constraint (model , constraint )
28
35
# Meta.index_together (RemovedInDjango51Warning)
29
36
for field_names in model ._meta .index_together :
30
37
index = Index (fields = field_names )
31
38
index .set_name_with_model (model )
32
39
self .add_index (model , index )
40
+ # Meta.constraints
41
+ for constraint in model ._meta .constraints :
42
+ self .add_constraint (model , constraint )
33
43
# Meta.indexes
34
44
for index in model ._meta .indexes :
35
45
self .add_index (model , index )
@@ -56,6 +66,11 @@ def add_field(self, model, field):
56
66
index = Index (fields = [field .name ])
57
67
index .name = self ._create_index_name (model ._meta .db_table , [field .column ])
58
68
self .add_index (model , index , field = field )
69
+ if field .unique and field .column != "_id" :
70
+ constraint = UniqueConstraint (
71
+ fields = [field .name ], name = f"{ model ._meta .db_table } _{ field .column } _key"
72
+ )
73
+ self .add_constraint (model , constraint , field = field )
59
74
60
75
def _alter_field (
61
76
self ,
@@ -148,9 +163,19 @@ def alter_index_together(self, model, old_index_together, new_index_together):
148
163
def alter_unique_together (self , model , old_unique_together , new_unique_together ):
149
164
pass
150
165
151
- def add_index (self , model , index , field = None ):
166
+ def add_index (self , model , index , field = None , unique = False ):
152
167
if index .contains_expressions :
153
168
return
169
+ kwargs = {}
170
+ if unique :
171
+ filter_expression = {}
172
+ if field :
173
+ filter_expression [field .column ] = {"$type" : field .db_type (self .connection )}
174
+ else :
175
+ for field_name , _ in index .fields_orders :
176
+ field_ = model ._meta .get_field (field_name )
177
+ filter_expression [field_ .column ] = {"$type" : field_ .db_type (self .connection )}
178
+ kwargs = {"partialFilterExpression" : filter_expression , "unique" : True }
154
179
index_orders = (
155
180
[(field .column , 1 )]
156
181
if field
@@ -162,6 +187,7 @@ def add_index(self, model, index, field=None):
162
187
idx = IndexModel (
163
188
index_orders ,
164
189
name = index .name ,
190
+ ** kwargs ,
165
191
)
166
192
self .connection .database [model ._meta .db_table ].create_indexes ([idx ])
167
193
@@ -170,11 +196,27 @@ def remove_index(self, model, index):
170
196
return
171
197
self .connection .database [model ._meta .db_table ].drop_index (index .name )
172
198
173
- def add_constraint (self , model , constraint ):
174
- pass
199
+ def add_constraint (self , model , constraint , field = None ):
200
+ if isinstance (constraint , UniqueConstraint ) and self ._unique_supported (
201
+ condition = constraint .condition ,
202
+ deferrable = constraint .deferrable ,
203
+ include = constraint .include ,
204
+ expressions = constraint .expressions ,
205
+ nulls_distinct = constraint .nulls_distinct ,
206
+ ):
207
+ idx = Index (fields = constraint .fields , name = constraint .name )
208
+ self .add_index (model , idx , field = field , unique = True )
175
209
176
210
def remove_constraint (self , model , constraint ):
177
- pass
211
+ if isinstance (constraint , UniqueConstraint ) and self ._unique_supported (
212
+ condition = constraint .condition ,
213
+ deferrable = constraint .deferrable ,
214
+ include = constraint .include ,
215
+ expressions = constraint .expressions ,
216
+ nulls_distinct = constraint .nulls_distinct ,
217
+ ):
218
+ idx = Index (fields = constraint .fields , name = constraint .name )
219
+ self .remove_index (model , idx )
178
220
179
221
def alter_db_table (self , model , old_db_table , new_db_table ):
180
222
if old_db_table == new_db_table :
0 commit comments