@@ -109,6 +109,30 @@ def _alter_field(
109
109
strict = False ,
110
110
):
111
111
collection = self .connection .database [model ._meta .db_table ]
112
+ # Has unique been removed?
113
+ if old_field .unique and (
114
+ not new_field .unique or self ._field_became_primary_key (old_field , new_field )
115
+ ):
116
+ # Find the unique constraint for this field
117
+ meta_constraint_names = {constraint .name for constraint in model ._meta .constraints }
118
+ constraint_names = self ._constraint_names (
119
+ model ,
120
+ [old_field .column ],
121
+ unique = True ,
122
+ primary_key = False ,
123
+ exclude = meta_constraint_names ,
124
+ )
125
+ if strict and len (constraint_names ) != 1 :
126
+ raise ValueError (
127
+ f"Found wrong number ({ len (constraint_names )} ) of unique "
128
+ f"constraints for { model ._meta .db_table } .{ old_field .column } "
129
+ )
130
+ for constraint_name in constraint_names :
131
+ constraint = UniqueConstraint (
132
+ fields = [old_field .name ],
133
+ name = constraint_name ,
134
+ )
135
+ self .remove_constraint (model , constraint )
112
136
# Removed an index? (no strict check, as multiple indexes are possible)
113
137
# Remove indexes if db_index switched to False or a unique constraint
114
138
# will now be used in lieu of an index. The following lines from the
@@ -134,12 +158,29 @@ def _alter_field(
134
158
):
135
159
self ._drop_index_for_field (model , old_field )
136
160
self ._add_index_for_field (model , new_field )
161
+ # Move unique to the new field, if needed.
162
+ if old_field .unique and new_field .unique and new_field .column != "_id" :
163
+ if not old_field .primary_key :
164
+ old_constraint = UniqueConstraint (
165
+ fields = [old_field .name ], name = f"{ model ._meta .db_table } _{ old_field .column } _key"
166
+ )
167
+ self .remove_constraint (model , old_constraint )
168
+ new_constraint = UniqueConstraint (
169
+ fields = [new_field .name ], name = f"{ model ._meta .db_table } _{ new_field .column } _key"
170
+ )
171
+ self .add_constraint (model , new_constraint , field = new_field )
137
172
# Replace NULL with the field default if the field and was changed from
138
173
# NULL to NOT NULL.
139
174
if new_field .has_default () and old_field .null and not new_field .null :
140
175
column = new_field .column
141
176
default = self .effective_default (new_field )
142
177
collection .update_many ({column : {"$eq" : None }}, [{"$set" : {column : default }}])
178
+ # Added a unique?
179
+ if self ._unique_should_be_added (old_field , new_field ):
180
+ constraint = UniqueConstraint (
181
+ fields = [new_field .name ], name = f"{ model ._meta .db_table } _{ new_field .column } _key"
182
+ )
183
+ self .add_constraint (model , constraint , field = new_field )
143
184
# Added an index? Add an index if db_index switched to True or a unique
144
185
# constraint will no longer be used in lieu of an index. The following
145
186
# lines from the truth table show all True cases; the rest are False:
0 commit comments