Skip to content

Commit

Permalink
Merge pull request #4146 from xiaohanyu/bug-fix-unique-validator-erro…
Browse files Browse the repository at this point in the history
…r-with-related-field

Fix #3844, refine validator for fields with <source=> kwargs
  • Loading branch information
xordoquy committed May 26, 2016
2 parents 35ace2e + 19bdfda commit 2d20f09
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
6 changes: 3 additions & 3 deletions rest_framework/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def set_context(self, serializer_field):
"""
# Determine the underlying model field name. This may not be the
# same as the serializer field name if `source=<>` is set.
self.field_name = serializer_field.source_attrs[0]
self.field_name = serializer_field.source_attrs[-1]
# Determine the existing instance, if this is an update operation.
self.instance = getattr(serializer_field.parent, 'instance', None)

Expand Down Expand Up @@ -174,8 +174,8 @@ def set_context(self, serializer):
"""
# Determine the underlying model field names. These may not be the
# same as the serializer field names if `source=<>` is set.
self.field_name = serializer.fields[self.field].source_attrs[0]
self.date_field_name = serializer.fields[self.date_field].source_attrs[0]
self.field_name = serializer.fields[self.field].source_attrs[-1]
self.date_field_name = serializer.fields[self.date_field].source_attrs[-1]
# Determine the existing instance, if this is an update operation.
self.instance = getattr(serializer, 'instance', None)

Expand Down
25 changes: 25 additions & 0 deletions tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.test import TestCase

from rest_framework import serializers
from rest_framework.validators import UniqueValidator


def dedent(blocktext):
Expand All @@ -22,6 +23,20 @@ class Meta:
model = UniquenessModel


class RelatedModel(models.Model):
user = models.OneToOneField(UniquenessModel, on_delete=models.CASCADE)
email = models.CharField(unique=True, max_length=80)


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

class Meta:
model = RelatedModel
fields = ('username', 'email')


class AnotherUniquenessModel(models.Model):
code = models.IntegerField(unique=True)

Expand Down Expand Up @@ -73,6 +88,16 @@ def test_doesnt_pollute_model(self):
self.assertEqual(
AnotherUniquenessModel._meta.get_field('code').validators, [])

def test_related_model_is_unique(self):
data = {'username': 'existing', 'email': '[email protected]'}
rs = RelatedModelSerializer(data=data)
self.assertFalse(rs.is_valid())
self.assertEqual(rs.errors,
{'username': ['This field must be unique.']})
data = {'username': 'new-username', 'email': '[email protected]'}
rs = RelatedModelSerializer(data=data)
self.assertTrue(rs.is_valid())


# Tests for `UniqueTogetherValidator`
# -----------------------------------
Expand Down

0 comments on commit 2d20f09

Please sign in to comment.