aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Christie2014-11-10 12:32:03 +0000
committerTom Christie2014-11-10 12:32:03 +0000
commitfd7db776addbd5e30f132fe6846ec5c5caab5c40 (patch)
tree27d46462bca33a82152125ac1d12c23223d64dc4
parent8c1fa0b87d9c195420dd7a24c3bdf1b7d3295f1b (diff)
downloaddjango-rest-framework-fd7db776addbd5e30f132fe6846ec5c5caab5c40.tar.bz2
Bring UniqueValidator implementation in line with other uniquness validators.
-rw-r--r--docs/api-guide/validators.md6
-rw-r--r--rest_framework/validators.py22
2 files changed, 21 insertions, 7 deletions
diff --git a/docs/api-guide/validators.md b/docs/api-guide/validators.md
index bb073f57..a50636bc 100644
--- a/docs/api-guide/validators.md
+++ b/docs/api-guide/validators.md
@@ -16,9 +16,9 @@ Validation in Django REST framework serializers is handled a little differently
With `ModelForm` the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class. This is advantageous for the following reasons:
-* It introduces a proper separation of concerns, making your code behaviour more obvious.
-* It is easy to switch between using shortcut `ModelSerializer` classes and using explicit `Serializer` classes. Any validation behaviour being used for `ModelSerializer` is simple to replicate.
-* Printing the `repr` of a serializer instance will show you exactly what validation rules it applies. There's no extra hidden validation behaviour being called on the model instance.
+* It introduces a proper separation of concerns, making your code behavior more obvious.
+* It is easy to switch between using shortcut `ModelSerializer` classes and using explicit `Serializer` classes. Any validation behavior being used for `ModelSerializer` is simple to replicate.
+* Printing the `repr` of a serializer instance will show you exactly what validation rules it applies. There's no extra hidden validation behavior being called on the model instance.
When you're using `ModelSerializer` all of this is handled automatically for you. If you want to drop down to using a `Serializer` classes instead, then you need to define the validation rules explicitly.
diff --git a/rest_framework/validators.py b/rest_framework/validators.py
index d7f847aa..fa4f1847 100644
--- a/rest_framework/validators.py
+++ b/rest_framework/validators.py
@@ -35,12 +35,26 @@ class UniqueValidator:
# Determine the existing instance, if this is an update operation.
self.instance = getattr(serializer_field.parent, 'instance', None)
- def __call__(self, value):
- # Ensure uniqueness.
+ def filter_queryset(self, value, queryset):
+ """
+ Filter the queryset to all instances matching the given attribute.
+ """
filter_kwargs = {self.field_name: value}
- queryset = self.queryset.filter(**filter_kwargs)
+ return queryset.filter(**filter_kwargs)
+
+ def exclude_current_instance(self, queryset):
+ """
+ If an instance is being updated, then do not include
+ that instance itself as a uniqueness conflict.
+ """
if self.instance is not None:
- queryset = queryset.exclude(pk=self.instance.pk)
+ return queryset.exclude(pk=self.instance.pk)
+ return queryset
+
+ def __call__(self, value):
+ queryset = self.queryset
+ queryset = self.filter_queryset(value, queryset)
+ queryset = self.exclude_current_instance(queryset)
if queryset.exists():
raise ValidationError(self.message)