mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-06 13:30:12 +03:00
Merge 518f6ebb57
into f7917928c0
This commit is contained in:
commit
7aa0256018
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue
Block a user