@@ -184,11 +184,23 @@ def _do_update(model_instance, base_qs, using, pk_val, values, update_fields, fo
184
184
# else:
185
185
# new_version = old_version
186
186
break
187
- if values :
187
+
188
+ # This provides a default if either (1) no values were provided or (2) we reached this code as part of a
189
+ # create. We don't need to worry about a race condition because a competing create should produce an
190
+ # error anyway.
191
+ updated = base_qs .filter (pk = pk_val ).exists ()
192
+
193
+ # This second situation can occur because `Model.save_base` calls `Model._save_parent` without relaying
194
+ # the `force_insert` flag that marks the process as a create. Eventually, `Model._save_table` will call
195
+ # this function as-if it were in the middle of an update. The update is expected to fail because there
196
+ # is no object to update and the caller will fall back on the create logic instead. We need to ensure
197
+ # the update fails (but does not raise an exception) under this circumstance by skipping the concurrency
198
+ # logic.
199
+ if values and updated :
188
200
if (model_instance ._concurrencymeta .enabled and
189
201
conf .ENABLED and
190
202
not getattr (model_instance , '_concurrency_disabled' , False ) and
191
- old_version ):
203
+ ( old_version or not conf . IGNORE_DEFAULT ) ):
192
204
filter_kwargs = {'pk' : pk_val , version_field .attname : old_version }
193
205
updated = base_qs .filter (** filter_kwargs )._update (values ) >= 1
194
206
if not updated :
@@ -197,8 +209,6 @@ def _do_update(model_instance, base_qs, using, pk_val, values, update_fields, fo
197
209
else :
198
210
filter_kwargs = {'pk' : pk_val }
199
211
updated = base_qs .filter (** filter_kwargs )._update (values ) >= 1
200
- else :
201
- updated = base_qs .filter (pk = pk_val ).exists ()
202
212
203
213
return updated
204
214
0 commit comments