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,19 @@ def _create_model_indexes(self, model):
25
25
index = Index (fields = [field .name ])
26
26
index .set_name_with_model (model )
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 (fields = [field .name ], name = "%s_uniq" % field .column )
32
+ self .add_constraint (model , constraint )
28
33
# Meta.index_together (RemovedInDjango51Warning)
29
34
for field_names in model ._meta .index_together :
30
35
index = Index (fields = field_names )
31
36
index .set_name_with_model (model )
32
37
self .add_index (model , index )
38
+ # Meta.constraints
39
+ for constraint in model ._meta .constraints :
40
+ self .add_constraint (model , constraint )
33
41
# Meta.indexes
34
42
for index in model ._meta .indexes :
35
43
self .add_index (model , index )
@@ -95,15 +103,23 @@ def alter_index_together(self, model, old_index_together, new_index_together):
95
103
def alter_unique_together (self , model , old_unique_together , new_unique_together ):
96
104
pass
97
105
98
- def add_index (self , model , index ):
106
+ def add_index (self , model , index , unique = False ):
99
107
if index .contains_expressions :
100
108
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 }
101
116
idx = IndexModel (
102
117
[
103
118
(model ._meta .get_field (field_name ).column , 1 if order == "" else - 1 )
104
119
for field_name , order in index .fields_orders
105
120
],
106
121
name = index .name ,
122
+ ** kwargs ,
107
123
)
108
124
self .connection .database [model ._meta .db_table ].create_indexes ([idx ])
109
125
@@ -113,10 +129,26 @@ def remove_index(self, model, index):
113
129
self .connection .database [model ._meta .db_table ].drop_index (index .name )
114
130
115
131
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 )
117
141
118
142
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 )
120
152
121
153
def alter_db_table (self , model , old_db_table , new_db_table ):
122
154
if old_db_table == new_db_table :
0 commit comments