mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-11 04:07:39 +03:00
Merge pull request #5078 from rooterkyberian/issue-4748
add URL path unquote to HyperlinkedRelatedField.to_internal_value
This commit is contained in:
commit
ee1a9fcef6
|
@ -7,7 +7,9 @@ from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
|
|||
from django.db.models import Manager
|
||||
from django.db.models.query import QuerySet
|
||||
from django.utils import six
|
||||
from django.utils.encoding import python_2_unicode_compatible, smart_text
|
||||
from django.utils.encoding import (
|
||||
python_2_unicode_compatible, smart_text, uri_to_iri
|
||||
)
|
||||
from django.utils.six.moves.urllib import parse as urlparse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
@ -324,6 +326,8 @@ class HyperlinkedRelatedField(RelatedField):
|
|||
if data.startswith(prefix):
|
||||
data = '/' + data[len(prefix):]
|
||||
|
||||
data = uri_to_iri(data)
|
||||
|
||||
try:
|
||||
match = resolve(data)
|
||||
except Resolver404:
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import uuid
|
||||
|
||||
import pytest
|
||||
from django.conf.urls import url
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.test import override_settings
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
|
||||
from rest_framework import serializers
|
||||
|
@ -87,10 +89,21 @@ class TestProxiedPrimaryKeyRelatedField(APISimpleTestCase):
|
|||
assert representation == self.instance.pk.int
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF=[
|
||||
url(r'^example/(?P<name>.+)/$', lambda: None, name='example'),
|
||||
])
|
||||
class TestHyperlinkedRelatedField(APISimpleTestCase):
|
||||
def setUp(self):
|
||||
self.queryset = MockQueryset([
|
||||
MockObject(pk=1, name='foobar'),
|
||||
MockObject(pk=2, name='baz qux'),
|
||||
])
|
||||
self.field = serializers.HyperlinkedRelatedField(
|
||||
view_name='example', read_only=True)
|
||||
view_name='example',
|
||||
lookup_field='name',
|
||||
lookup_url_kwarg='name',
|
||||
queryset=self.queryset,
|
||||
)
|
||||
self.field.reverse = mock_reverse
|
||||
self.field._context = {'request': True}
|
||||
|
||||
|
@ -98,6 +111,20 @@ class TestHyperlinkedRelatedField(APISimpleTestCase):
|
|||
representation = self.field.to_representation(MockObject(pk=''))
|
||||
assert representation is None
|
||||
|
||||
def test_hyperlinked_related_lookup_exists(self):
|
||||
instance = self.field.to_internal_value('http://example.org/example/foobar/')
|
||||
assert instance is self.queryset.items[0]
|
||||
|
||||
def test_hyperlinked_related_lookup_url_encoded_exists(self):
|
||||
instance = self.field.to_internal_value('http://example.org/example/baz%20qux/')
|
||||
assert instance is self.queryset.items[1]
|
||||
|
||||
def test_hyperlinked_related_lookup_does_not_exist(self):
|
||||
with pytest.raises(serializers.ValidationError) as excinfo:
|
||||
self.field.to_internal_value('http://example.org/example/doesnotexist/')
|
||||
msg = excinfo.value.detail[0]
|
||||
assert msg == 'Invalid hyperlink - Object does not exist.'
|
||||
|
||||
|
||||
class TestHyperlinkedIdentityField(APISimpleTestCase):
|
||||
def setUp(self):
|
||||
|
|
|
@ -156,6 +156,7 @@ class TestCustomLookupFields(TestCase):
|
|||
"""
|
||||
def setUp(self):
|
||||
RouterTestModel.objects.create(uuid='123', text='foo bar')
|
||||
RouterTestModel.objects.create(uuid='a b', text='baz qux')
|
||||
|
||||
def test_custom_lookup_field_route(self):
|
||||
detail_route = notes_router.urls[-1]
|
||||
|
@ -164,12 +165,19 @@ class TestCustomLookupFields(TestCase):
|
|||
|
||||
def test_retrieve_lookup_field_list_view(self):
|
||||
response = self.client.get('/example/notes/')
|
||||
assert response.data == [{"url": "http://testserver/example/notes/123/", "uuid": "123", "text": "foo bar"}]
|
||||
assert response.data == [
|
||||
{"url": "http://testserver/example/notes/123/", "uuid": "123", "text": "foo bar"},
|
||||
{"url": "http://testserver/example/notes/a%20b/", "uuid": "a b", "text": "baz qux"},
|
||||
]
|
||||
|
||||
def test_retrieve_lookup_field_detail_view(self):
|
||||
response = self.client.get('/example/notes/123/')
|
||||
assert response.data == {"url": "http://testserver/example/notes/123/", "uuid": "123", "text": "foo bar"}
|
||||
|
||||
def test_retrieve_lookup_field_url_encoded_detail_view_(self):
|
||||
response = self.client.get('/example/notes/a%20b/')
|
||||
assert response.data == {"url": "http://testserver/example/notes/a%20b/", "uuid": "a b", "text": "baz qux"}
|
||||
|
||||
|
||||
class TestLookupValueRegex(TestCase):
|
||||
"""
|
||||
|
@ -211,6 +219,10 @@ class TestLookupUrlKwargs(TestCase):
|
|||
response = self.client.get('/example2/notes/fo/')
|
||||
assert response.data == {"url": "http://testserver/example/notes/123/", "uuid": "123", "text": "foo bar"}
|
||||
|
||||
def test_retrieve_lookup_url_encoded_kwarg_detail_view(self):
|
||||
response = self.client.get('/example2/notes/foo%20bar/')
|
||||
assert response.data == {"url": "http://testserver/example/notes/123/", "uuid": "123", "text": "foo bar"}
|
||||
|
||||
|
||||
class TestTrailingSlashIncluded(TestCase):
|
||||
def setUp(self):
|
||||
|
|
Loading…
Reference in New Issue
Block a user