From 64ff8c5b0b3482a42aaf16236b86e3d2cff86579 Mon Sep 17 00:00:00 2001 From: orf Date: Mon, 24 Apr 2017 20:55:16 +0100 Subject: [PATCH 1/5] #4917 - Remove O(n) queries in m2m updates --- rest_framework/relations.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index eac9647b00..f5d83c68b2 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -491,11 +491,14 @@ def to_internal_value(self, data): self.fail('not_a_list', input_type=type(data).__name__) if not self.allow_empty and len(data) == 0: self.fail('empty') - - return [ - self.child_relation.to_internal_value(item) - for item in data - ] + + values = list(self.child_relation.get_queryset.filter(pk__in=data)) + missing_primary_keys = set(v.pk for v in values) - set(data) + + if missing_primary_keys: + self.fail('missing_ids', ids_not_found=list(missing_primary_keys)) + + return values def get_attribute(self, instance): # Can't have any relationships if not created From 54bb9849c2dc3d43dfbab81d5c3b406e935ebd5d Mon Sep 17 00:00:00 2001 From: orf Date: Mon, 24 Apr 2017 20:58:08 +0100 Subject: [PATCH 2/5] Update relations.py --- rest_framework/relations.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index f5d83c68b2..dca6a26345 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -492,11 +492,17 @@ def to_internal_value(self, data): if not self.allow_empty and len(data) == 0: self.fail('empty') - values = list(self.child_relation.get_queryset.filter(pk__in=data)) - missing_primary_keys = set(v.pk for v in values) - set(data) + if self.child_relation.use_pk_only_optimization: + values = list(self.child_relation.get_queryset.filter(pk__in=data)) + missing_primary_keys = set(v.pk for v in values) - set(data) - if missing_primary_keys: - self.fail('missing_ids', ids_not_found=list(missing_primary_keys)) + if missing_primary_keys: + self.fail('missing_ids', ids_not_found=list(missing_primary_keys)) + else: + values = [ + self.child_relation.to_internal_value(item) + for item in data + ] return values From 1d990eaba10d542978cbf35d57497858e6f0c3a7 Mon Sep 17 00:00:00 2001 From: orf Date: Mon, 24 Apr 2017 20:58:42 +0100 Subject: [PATCH 3/5] Update relations.py --- rest_framework/relations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index dca6a26345..a07434172f 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -493,7 +493,7 @@ def to_internal_value(self, data): self.fail('empty') if self.child_relation.use_pk_only_optimization: - values = list(self.child_relation.get_queryset.filter(pk__in=data)) + values = list(self.child_relation.get_queryset().filter(pk__in=data)) missing_primary_keys = set(v.pk for v in values) - set(data) if missing_primary_keys: From 1538f53ef86d45811b5f581b3e1c82dacea88c4c Mon Sep 17 00:00:00 2001 From: orf Date: Mon, 24 Apr 2017 21:23:55 +0100 Subject: [PATCH 4/5] Update relations.py --- rest_framework/relations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index a07434172f..2c88071fd9 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -492,7 +492,7 @@ def to_internal_value(self, data): if not self.allow_empty and len(data) == 0: self.fail('empty') - if self.child_relation.use_pk_only_optimization: + if isinstance(self.child_relation, PrimaryKeyRelatedField): values = list(self.child_relation.get_queryset().filter(pk__in=data)) missing_primary_keys = set(v.pk for v in values) - set(data) From ecf8c6f6ff4ecb6b5289d58c377ef45283b9fb0c Mon Sep 17 00:00:00 2001 From: orf Date: Mon, 24 Apr 2017 21:33:19 +0100 Subject: [PATCH 5/5] Update relations.py --- rest_framework/relations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index 2c88071fd9..1ca1a03ec8 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -491,11 +491,11 @@ def to_internal_value(self, data): self.fail('not_a_list', input_type=type(data).__name__) if not self.allow_empty and len(data) == 0: self.fail('empty') - + if isinstance(self.child_relation, PrimaryKeyRelatedField): values = list(self.child_relation.get_queryset().filter(pk__in=data)) missing_primary_keys = set(v.pk for v in values) - set(data) - + if missing_primary_keys: self.fail('missing_ids', ids_not_found=list(missing_primary_keys)) else: