summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2019-02-15 01:01:25 -0500
committerTim Graham <timograham@gmail.com>2019-02-21 10:20:47 -0500
commit28712d8acfffa9cdabb88cb610bae14913fa185d (patch)
treec2237f1578ddf7a1c3a6d975a5a972d0ed59a295 /django/db
parentdd32f9a3a21272e784d434a6f9ca9f07aeedb50a (diff)
Refs #19544 -- Ignored auto-created through additions conflicts if supported.
This prevents IntegrityError caused by race conditions between missing ids retrieval and bulk insertions.
Diffstat (limited to 'django/db')
-rw-r--r--django/db/models/fields/related_descriptors.py10
1 files changed, 8 insertions, 2 deletions
diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py
index 96b8a37583..52cb91d3a8 100644
--- a/django/db/models/fields/related_descriptors.py
+++ b/django/db/models/fields/related_descriptors.py
@@ -1110,14 +1110,20 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
model=self.model, pk_set=missing_target_ids, using=db,
)
- # Add the ones that aren't there already
+ # Add the ones that aren't there already. Conflicts can be
+ # ignored when the intermediary model is auto-created as
+ # the only possible collision is on the (sid_id, tid_id)
+ # tuple. The same assertion doesn't hold for user-defined
+ # intermediary models as they could have other fields
+ # causing conflicts which must be surfaced.
+ ignore_conflicts = self.through._meta.auto_created is not False
self.through._default_manager.using(db).bulk_create([
self.through(**through_defaults, **{
'%s_id' % source_field_name: self.related_val[0],
'%s_id' % target_field_name: target_id,
})
for target_id in missing_target_ids
- ])
+ ], ignore_conflicts=ignore_conflicts)
if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are inserting the