From 83d5da54ca4f2770bc57e839fcdeb7919bd03459 Mon Sep 17 00:00:00 2001 From: Miroslav Shubernetskiy Date: Wed, 18 Feb 2015 23:02:45 -0500 Subject: [PATCH 1/3] fix in UniqueTogetherValidator to allow it to handle querysets this is especially important when using a serializer with many=True and the model having unique multiple constrains --- rest_framework/validators.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rest_framework/validators.py b/rest_framework/validators.py index e3719b8d5c..4b4321a0d0 100644 --- a/rest_framework/validators.py +++ b/rest_framework/validators.py @@ -7,6 +7,7 @@ `ModelSerializer` class and an equivalent explicit `Serializer` class. """ from __future__ import unicode_literals +from django.db import models from django.utils.translation import ugettext_lazy as _ from rest_framework.compat import unicode_to_repr from rest_framework.exceptions import ValidationError @@ -112,7 +113,7 @@ def filter_queryset(self, attrs, queryset): """ # If this is an update, then any unprovided field should # have it's value set based on the existing instance attribute. - if self.instance is not None: + if self.instance is not None and isinstance(self.instance, models.Model): for field_name in self.fields: if field_name not in attrs: attrs[field_name] = getattr(self.instance, field_name) @@ -121,6 +122,7 @@ def filter_queryset(self, attrs, queryset): filter_kwargs = dict([ (field_name, attrs[field_name]) for field_name in self.fields + if field_name in attrs ]) return queryset.filter(**filter_kwargs) @@ -130,7 +132,10 @@ def exclude_current_instance(self, attrs, queryset): that instance itself as a uniqueness conflict. """ if self.instance is not None: - return queryset.exclude(pk=self.instance.pk) + if isinstance(self.instance, models.QuerySet): + return queryset.exclude(pk__in=self.instance.values_list('pk', flat=True)) + else: + return queryset.exclude(pk=self.instance.pk) return queryset def __call__(self, attrs): From 14b8d22346f97cf29a1739060eeab5cfaa096052 Mon Sep 17 00:00:00 2001 From: Miroslav Shubernetskiy Date: Fri, 20 Feb 2015 18:13:15 -0500 Subject: [PATCH 2/3] explicitly importing QuerySet to fix failing import in older Django versions --- rest_framework/validators.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rest_framework/validators.py b/rest_framework/validators.py index 4b4321a0d0..1fef3d6a75 100644 --- a/rest_framework/validators.py +++ b/rest_framework/validators.py @@ -8,6 +8,7 @@ """ from __future__ import unicode_literals from django.db import models +from django.db.models.query import QuerySet from django.utils.translation import ugettext_lazy as _ from rest_framework.compat import unicode_to_repr from rest_framework.exceptions import ValidationError @@ -132,7 +133,7 @@ def exclude_current_instance(self, attrs, queryset): that instance itself as a uniqueness conflict. """ if self.instance is not None: - if isinstance(self.instance, models.QuerySet): + if isinstance(self.instance, QuerySet): return queryset.exclude(pk__in=self.instance.values_list('pk', flat=True)) else: return queryset.exclude(pk=self.instance.pk) From 3866a1be70b7a48dd858e037cd66d89f682e0976 Mon Sep 17 00:00:00 2001 From: Miroslav Shubernetskiy Date: Fri, 20 Feb 2015 18:16:08 -0500 Subject: [PATCH 3/3] using SQL in exclude() vs manually compiling pks to exclude --- rest_framework/validators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/validators.py b/rest_framework/validators.py index 1fef3d6a75..dc02af7a84 100644 --- a/rest_framework/validators.py +++ b/rest_framework/validators.py @@ -134,7 +134,7 @@ def exclude_current_instance(self, attrs, queryset): """ if self.instance is not None: if isinstance(self.instance, QuerySet): - return queryset.exclude(pk__in=self.instance.values_list('pk', flat=True)) + return queryset.exclude(pk__in=self.instance.all()) else: return queryset.exclude(pk=self.instance.pk) return queryset