Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
django-rest-framework
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
django-rest-framework
Commits
5e185aa2
Commit
5e185aa2
authored
Apr 14, 2017
by
Maciej Urbanski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add URL path unquote to HyperlinkedRelatedField.to_internal_value
parent
fd72a814
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
46 additions
and
3 deletions
+46
-3
rest_framework/relations.py
+5
-1
tests/test_relations.py
+28
-1
tests/test_routers.py
+13
-1
No files found.
rest_framework/relations.py
View file @
5e185aa2
...
@@ -7,7 +7,9 @@ from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
...
@@ -7,7 +7,9 @@ from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from
django.db.models
import
Manager
from
django.db.models
import
Manager
from
django.db.models.query
import
QuerySet
from
django.db.models.query
import
QuerySet
from
django.utils
import
six
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.six.moves.urllib
import
parse
as
urlparse
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
...
@@ -324,6 +326,8 @@ class HyperlinkedRelatedField(RelatedField):
...
@@ -324,6 +326,8 @@ class HyperlinkedRelatedField(RelatedField):
if
data
.
startswith
(
prefix
):
if
data
.
startswith
(
prefix
):
data
=
'/'
+
data
[
len
(
prefix
):]
data
=
'/'
+
data
[
len
(
prefix
):]
data
=
uri_to_iri
(
data
)
try
:
try
:
match
=
resolve
(
data
)
match
=
resolve
(
data
)
except
Resolver404
:
except
Resolver404
:
...
...
tests/test_relations.py
View file @
5e185aa2
import
uuid
import
uuid
import
pytest
import
pytest
from
django.conf.urls
import
url
from
django.core.exceptions
import
ImproperlyConfigured
from
django.core.exceptions
import
ImproperlyConfigured
from
django.test
import
override_settings
from
django.utils.datastructures
import
MultiValueDict
from
django.utils.datastructures
import
MultiValueDict
from
rest_framework
import
serializers
from
rest_framework
import
serializers
...
@@ -87,10 +89,21 @@ class TestProxiedPrimaryKeyRelatedField(APISimpleTestCase):
...
@@ -87,10 +89,21 @@ class TestProxiedPrimaryKeyRelatedField(APISimpleTestCase):
assert
representation
==
self
.
instance
.
pk
.
int
assert
representation
==
self
.
instance
.
pk
.
int
@override_settings
(
ROOT_URLCONF
=
[
url
(
r'^example/(?P<name>.+)/$'
,
lambda
:
None
,
name
=
'example'
),
])
class
TestHyperlinkedRelatedField
(
APISimpleTestCase
):
class
TestHyperlinkedRelatedField
(
APISimpleTestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
queryset
=
MockQueryset
([
MockObject
(
pk
=
1
,
name
=
'foobar'
),
MockObject
(
pk
=
2
,
name
=
'baz qux'
),
])
self
.
field
=
serializers
.
HyperlinkedRelatedField
(
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
.
reverse
=
mock_reverse
self
.
field
.
_context
=
{
'request'
:
True
}
self
.
field
.
_context
=
{
'request'
:
True
}
...
@@ -98,6 +111,20 @@ class TestHyperlinkedRelatedField(APISimpleTestCase):
...
@@ -98,6 +111,20 @@ class TestHyperlinkedRelatedField(APISimpleTestCase):
representation
=
self
.
field
.
to_representation
(
MockObject
(
pk
=
''
))
representation
=
self
.
field
.
to_representation
(
MockObject
(
pk
=
''
))
assert
representation
is
None
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
%20
qux/'
)
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
):
class
TestHyperlinkedIdentityField
(
APISimpleTestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
...
...
tests/test_routers.py
View file @
5e185aa2
...
@@ -156,6 +156,7 @@ class TestCustomLookupFields(TestCase):
...
@@ -156,6 +156,7 @@ class TestCustomLookupFields(TestCase):
"""
"""
def
setUp
(
self
):
def
setUp
(
self
):
RouterTestModel
.
objects
.
create
(
uuid
=
'123'
,
text
=
'foo bar'
)
RouterTestModel
.
objects
.
create
(
uuid
=
'123'
,
text
=
'foo bar'
)
RouterTestModel
.
objects
.
create
(
uuid
=
'a b'
,
text
=
'baz qux'
)
def
test_custom_lookup_field_route
(
self
):
def
test_custom_lookup_field_route
(
self
):
detail_route
=
notes_router
.
urls
[
-
1
]
detail_route
=
notes_router
.
urls
[
-
1
]
...
@@ -164,12 +165,19 @@ class TestCustomLookupFields(TestCase):
...
@@ -164,12 +165,19 @@ class TestCustomLookupFields(TestCase):
def
test_retrieve_lookup_field_list_view
(
self
):
def
test_retrieve_lookup_field_list_view
(
self
):
response
=
self
.
client
.
get
(
'/example/notes/'
)
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
%20
b/"
,
"uuid"
:
"a b"
,
"text"
:
"baz qux"
},
]
def
test_retrieve_lookup_field_detail_view
(
self
):
def
test_retrieve_lookup_field_detail_view
(
self
):
response
=
self
.
client
.
get
(
'/example/notes/123/'
)
response
=
self
.
client
.
get
(
'/example/notes/123/'
)
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"
}
def
test_retrieve_lookup_field_url_encoded_detail_view_
(
self
):
response
=
self
.
client
.
get
(
'/example/notes/a
%20
b/'
)
assert
response
.
data
==
{
"url"
:
"http://testserver/example/notes/a
%20
b/"
,
"uuid"
:
"a b"
,
"text"
:
"baz qux"
}
class
TestLookupValueRegex
(
TestCase
):
class
TestLookupValueRegex
(
TestCase
):
"""
"""
...
@@ -211,6 +219,10 @@ class TestLookupUrlKwargs(TestCase):
...
@@ -211,6 +219,10 @@ class TestLookupUrlKwargs(TestCase):
response
=
self
.
client
.
get
(
'/example2/notes/fo/'
)
response
=
self
.
client
.
get
(
'/example2/notes/fo/'
)
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"
}
def
test_retrieve_lookup_url_encoded_kwarg_detail_view
(
self
):
response
=
self
.
client
.
get
(
'/example2/notes/foo
%20
bar/'
)
assert
response
.
data
==
{
"url"
:
"http://testserver/example/notes/123/"
,
"uuid"
:
"123"
,
"text"
:
"foo bar"
}
class
TestTrailingSlashIncluded
(
TestCase
):
class
TestTrailingSlashIncluded
(
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment