Skip to content

Commit

Permalink
Case insensitive uniqueness validation (encode#4534)
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanseymour authored and tomchristie committed Oct 4, 2016
1 parent 0b373be commit 883efbc
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/api-guide/validators.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ It takes a single required argument, and an optional `messages` argument:

* `queryset` *required* - This is the queryset against which uniqueness should be enforced.
* `message` - The error message that should be used when validation fails.
* `lookup` - The lookup used to find an existing instance with the value being validated. Defaults to `'exact'`.

This validator should be applied to *serializer fields*, like so:

Expand Down
5 changes: 3 additions & 2 deletions rest_framework/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ class UniqueValidator(object):
"""
message = _('This field must be unique.')

def __init__(self, queryset, message=None):
def __init__(self, queryset, message=None, lookup='exact'):
self.queryset = queryset
self.serializer_field = None
self.message = message or self.message
self.lookup = lookup

def set_context(self, serializer_field):
"""
Expand All @@ -62,7 +63,7 @@ def filter_queryset(self, value, queryset):
"""
Filter the queryset to all instances matching the given attribute.
"""
filter_kwargs = {self.field_name: value}
filter_kwargs = {'%s__%s' % (self.field_name, self.lookup): value}
return qs_filter(queryset, **filter_kwargs)

def exclude_current_instance(self, queryset):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class RelatedModel(models.Model):

class RelatedModelSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username',
validators=[UniqueValidator(queryset=UniquenessModel.objects.all())]) # NOQA
validators=[UniqueValidator(queryset=UniquenessModel.objects.all(), lookup='iexact')]) # NOQA

class Meta:
model = RelatedModel
Expand Down Expand Up @@ -103,7 +103,7 @@ def test_doesnt_pollute_model(self):
AnotherUniquenessModel._meta.get_field('code').validators, [])

def test_related_model_is_unique(self):
data = {'username': 'existing', 'email': '[email protected]'}
data = {'username': 'Existing', 'email': '[email protected]'}
rs = RelatedModelSerializer(data=data)
self.assertFalse(rs.is_valid())
self.assertEqual(rs.errors,
Expand Down

0 comments on commit 883efbc

Please sign in to comment.