This commit is contained in:
Christofer Bertonha 2015-03-05 23:21:52 +00:00
commit 7aa0256018
2 changed files with 53 additions and 0 deletions

View File

@ -320,6 +320,24 @@ class SlugRelatedField(RelatedField):
return getattr(obj, self.slug_field)
class MultipleSlugRelatedField(SlugRelatedField):
def __init__(self, separator=None, **kwargs):
assert separator is not None, 'The `separator` argument is required.'
self.separator = separator
super(MultipleSlugRelatedField, self).__init__(**kwargs)
def to_internal_value(self, data):
try:
return self.get_queryset().get(**dict(zip(self.slug_field, data.split(self.separator, len(self.slug_field)))))
except ObjectDoesNotExist:
self.fail('does_not_exist', slug_name=self.slug_field, value=smart_text(data))
except (TypeError, ValueError, AttributeError):
self.fail('invalid')
def to_representation(self, obj):
return six.text_type(obj)
class ManyRelatedField(Field):
"""
Relationships with `many=True` transparently get coerced into instead being

View File

@ -1,3 +1,4 @@
import six
from .utils import mock_reverse, fail_reverse, BadType, MockObject, MockQueryset
from django.core.exceptions import ImproperlyConfigured
from django.utils.datastructures import MultiValueDict
@ -138,6 +139,40 @@ class TestSlugRelatedField(APISimpleTestCase):
assert representation == self.instance.name
class TestMultipleSlugRelatedField(APISimpleTestCase):
def setUp(self):
self.queryset = MockQueryset([
MockObject(pk=1, name='foo', code='hamster'),
MockObject(pk=2, name='bar', code='bazinga'),
MockObject(pk=3, name='bar', code='cheeseshop')
])
self.instance = self.queryset.items[2]
self.field = serializers.MultipleSlugRelatedField(
slug_field=('name', 'code'), queryset=self.queryset, separator='-'
)
def test_slug_related_lookup_exists(self):
data = '{}-{}'.format(self.instance.name, self.instance.code)
instance = self.field.to_internal_value(data)
assert instance is self.instance
def test_slug_related_lookup_does_not_exist(self):
with pytest.raises(serializers.ValidationError) as excinfo:
self.field.to_internal_value('doesnotexist')
msg = excinfo.value.detail[0]
assert msg == 'Object with (\'name\', \'code\')=doesnotexist does not exist.'
def test_slug_related_lookup_invalid_type(self):
with pytest.raises(serializers.ValidationError) as excinfo:
self.field.to_internal_value(BadType())
msg = excinfo.value.detail[0]
assert msg == 'Invalid value.'
def test_representation(self):
representation = self.field.to_representation(self.instance)
assert representation == six.text_type(self.instance)
class TestManyRelatedField(APISimpleTestCase):
def setUp(self):
self.instance = MockObject(pk=1, name='foo')