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
65bbc4a1
Commit
65bbc4a1
authored
Feb 05, 2015
by
Tom Christie
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'brandoncazander-version-3.1-2489' into version-3.1
parents
41b21341
e1c45133
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
102 additions
and
24 deletions
+102
-24
rest_framework/relations.py
+13
-6
rest_framework/reverse.py
+1
-1
rest_framework/versioning.py
+4
-1
tests/test_relations_hyperlink.py
+3
-4
tests/test_versioning.py
+57
-12
tests/utils.py
+24
-0
No files found.
rest_framework/relations.py
View file @
65bbc4a1
# coding: utf-8
# coding: utf-8
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
django.core.exceptions
import
ObjectDoesNotExist
,
ImproperlyConfigured
from
django.core.exceptions
import
ObjectDoesNotExist
,
ImproperlyConfigured
from
django.core.urlresolvers
import
resolve
,
get_script_prefix
,
NoReverseMatch
,
Resolver404
from
django.core.urlresolvers
import
get_script_prefix
,
resolve
,
NoReverseMatch
,
Resolver404
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
smart_text
from
django.utils.encoding
import
smart_text
...
@@ -167,11 +167,10 @@ class HyperlinkedRelatedField(RelatedField):
...
@@ -167,11 +167,10 @@ class HyperlinkedRelatedField(RelatedField):
self
.
lookup_url_kwarg
=
kwargs
.
pop
(
'lookup_url_kwarg'
,
self
.
lookup_field
)
self
.
lookup_url_kwarg
=
kwargs
.
pop
(
'lookup_url_kwarg'
,
self
.
lookup_field
)
self
.
format
=
kwargs
.
pop
(
'format'
,
None
)
self
.
format
=
kwargs
.
pop
(
'format'
,
None
)
# We include th
ese
simply for dependency injection in tests.
# We include th
is
simply for dependency injection in tests.
# We can't add
them as class attributes or they
would expect an
# We can't add
it as a class attributes or it
would expect an
# implicit `self` argument to be passed.
# implicit `self` argument to be passed.
self
.
reverse
=
reverse
self
.
reverse
=
reverse
self
.
resolve
=
resolve
super
(
HyperlinkedRelatedField
,
self
)
.
__init__
(
**
kwargs
)
super
(
HyperlinkedRelatedField
,
self
)
.
__init__
(
**
kwargs
)
...
@@ -205,6 +204,7 @@ class HyperlinkedRelatedField(RelatedField):
...
@@ -205,6 +204,7 @@ class HyperlinkedRelatedField(RelatedField):
return
self
.
reverse
(
view_name
,
kwargs
=
kwargs
,
request
=
request
,
format
=
format
)
return
self
.
reverse
(
view_name
,
kwargs
=
kwargs
,
request
=
request
,
format
=
format
)
def
to_internal_value
(
self
,
data
):
def
to_internal_value
(
self
,
data
):
request
=
self
.
context
.
get
(
'request'
,
None
)
try
:
try
:
http_prefix
=
data
.
startswith
((
'http:'
,
'https:'
))
http_prefix
=
data
.
startswith
((
'http:'
,
'https:'
))
except
AttributeError
:
except
AttributeError
:
...
@@ -218,11 +218,18 @@ class HyperlinkedRelatedField(RelatedField):
...
@@ -218,11 +218,18 @@ class HyperlinkedRelatedField(RelatedField):
data
=
'/'
+
data
[
len
(
prefix
):]
data
=
'/'
+
data
[
len
(
prefix
):]
try
:
try
:
match
=
self
.
resolve
(
data
)
match
=
resolve
(
data
)
except
Resolver404
:
except
Resolver404
:
self
.
fail
(
'no_match'
)
self
.
fail
(
'no_match'
)
if
match
.
view_name
!=
self
.
view_name
:
try
:
expected_viewname
=
request
.
versioning_scheme
.
get_versioned_viewname
(
self
.
view_name
,
request
)
except
AttributeError
:
expected_viewname
=
self
.
view_name
if
match
.
view_name
!=
expected_viewname
:
self
.
fail
(
'incorrect_match'
)
self
.
fail
(
'incorrect_match'
)
try
:
try
:
...
...
rest_framework/reverse.py
View file @
65bbc4a1
"""
"""
Provide
reverse functions that return fully qualified URL
s
Provide
urlresolver functions that return fully qualified URLs or view name
s
"""
"""
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
django.core.urlresolvers
import
reverse
as
django_reverse
from
django.core.urlresolvers
import
reverse
as
django_reverse
...
...
rest_framework/versioning.py
View file @
65bbc4a1
...
@@ -122,11 +122,14 @@ class NamespaceVersioning(BaseVersioning):
...
@@ -122,11 +122,14 @@ class NamespaceVersioning(BaseVersioning):
def
reverse
(
self
,
viewname
,
args
=
None
,
kwargs
=
None
,
request
=
None
,
format
=
None
,
**
extra
):
def
reverse
(
self
,
viewname
,
args
=
None
,
kwargs
=
None
,
request
=
None
,
format
=
None
,
**
extra
):
if
request
.
version
is
not
None
:
if
request
.
version
is
not
None
:
viewname
=
request
.
version
+
':'
+
viewname
viewname
=
self
.
get_versioned_viewname
(
viewname
,
request
)
return
super
(
NamespaceVersioning
,
self
)
.
reverse
(
return
super
(
NamespaceVersioning
,
self
)
.
reverse
(
viewname
,
args
,
kwargs
,
request
,
format
,
**
extra
viewname
,
args
,
kwargs
,
request
,
format
,
**
extra
)
)
def
get_versioned_viewname
(
self
,
viewname
,
request
):
return
request
.
version
+
':'
+
viewname
class
HostNameVersioning
(
BaseVersioning
):
class
HostNameVersioning
(
BaseVersioning
):
"""
"""
...
...
tests/test_relations_hyperlink.py
View file @
65bbc4a1
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
django.conf.urls
import
patterns
,
url
from
django.conf.urls
import
url
from
django.test
import
TestCase
from
django.test
import
TestCase
from
rest_framework
import
serializers
from
rest_framework
import
serializers
from
rest_framework.test
import
APIRequestFactory
from
rest_framework.test
import
APIRequestFactory
...
@@ -14,8 +14,7 @@ request = factory.get('/') # Just to ensure we have a request in the serializer
...
@@ -14,8 +14,7 @@ request = factory.get('/') # Just to ensure we have a request in the serializer
dummy_view
=
lambda
request
,
pk
:
None
dummy_view
=
lambda
request
,
pk
:
None
urlpatterns
=
patterns
(
urlpatterns
=
[
''
,
url
(
r'^dummyurl/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'dummy-url'
),
url
(
r'^dummyurl/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'dummy-url'
),
url
(
r'^manytomanysource/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'manytomanysource-detail'
),
url
(
r'^manytomanysource/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'manytomanysource-detail'
),
url
(
r'^manytomanytarget/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'manytomanytarget-detail'
),
url
(
r'^manytomanytarget/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'manytomanytarget-detail'
),
...
@@ -24,7 +23,7 @@ urlpatterns = patterns(
...
@@ -24,7 +23,7 @@ urlpatterns = patterns(
url
(
r'^nullableforeignkeysource/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'nullableforeignkeysource-detail'
),
url
(
r'^nullableforeignkeysource/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'nullableforeignkeysource-detail'
),
url
(
r'^onetoonetarget/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'onetoonetarget-detail'
),
url
(
r'^onetoonetarget/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'onetoonetarget-detail'
),
url
(
r'^nullableonetoonesource/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'nullableonetoonesource-detail'
),
url
(
r'^nullableonetoonesource/(?P<pk>[0-9]+)/$'
,
dummy_view
,
name
=
'nullableonetoonesource-detail'
),
)
]
# ManyToMany
# ManyToMany
...
...
tests/test_versioning.py
View file @
65bbc4a1
from
.utils
import
MockObject
,
MockQueryset
,
UsingURLPatterns
from
django.conf.urls
import
include
,
url
from
django.conf.urls
import
include
,
url
from
django.core.exceptions
import
ObjectDoesNotExist
from
rest_framework
import
serializers
from
rest_framework
import
status
,
versioning
from
rest_framework
import
status
,
versioning
from
rest_framework.decorators
import
APIView
from
rest_framework.decorators
import
APIView
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
rest_framework.reverse
import
reverse
from
rest_framework.reverse
import
reverse
from
rest_framework.test
import
APIRequestFactory
,
APITestCase
from
rest_framework.test
import
APIRequestFactory
,
APITestCase
from
rest_framework.versioning
import
NamespaceVersioning
import
pytest
class
RequestVersionView
(
APIView
):
class
RequestVersionView
(
APIView
):
...
@@ -29,16 +34,7 @@ class RequestInvalidVersionView(APIView):
...
@@ -29,16 +34,7 @@ class RequestInvalidVersionView(APIView):
factory
=
APIRequestFactory
()
factory
=
APIRequestFactory
()
mock_view
=
lambda
request
:
None
mock_view
=
lambda
request
:
None
dummy_view
=
lambda
request
,
pk
:
None
included_patterns
=
[
url
(
r'^namespaced/$'
,
mock_view
,
name
=
'another'
),
]
urlpatterns
=
[
url
(
r'^v1/'
,
include
(
included_patterns
,
namespace
=
'v1'
)),
url
(
r'^another/$'
,
mock_view
,
name
=
'another'
),
url
(
r'^(?P<version>[^/]+)/another/$'
,
mock_view
,
name
=
'another'
)
]
class
TestRequestVersion
:
class
TestRequestVersion
:
...
@@ -114,8 +110,17 @@ class TestRequestVersion:
...
@@ -114,8 +110,17 @@ class TestRequestVersion:
assert
response
.
data
==
{
'version'
:
None
}
assert
response
.
data
==
{
'version'
:
None
}
class
TestURLReversing
(
APITestCase
):
class
TestURLReversing
(
UsingURLPatterns
,
APITestCase
):
urls
=
'tests.test_versioning'
included
=
[
url
(
r'^namespaced/$'
,
mock_view
,
name
=
'another'
),
url
(
r'^example/(?P<pk>\d+)/$'
,
dummy_view
,
name
=
'example-detail'
)
]
urlpatterns
=
[
url
(
r'^v1/'
,
include
(
included
,
namespace
=
'v1'
)),
url
(
r'^another/$'
,
mock_view
,
name
=
'another'
),
url
(
r'^(?P<version>[^/]+)/another/$'
,
mock_view
,
name
=
'another'
),
]
def
test_reverse_unversioned
(
self
):
def
test_reverse_unversioned
(
self
):
view
=
ReverseView
.
as_view
()
view
=
ReverseView
.
as_view
()
...
@@ -221,3 +226,43 @@ class TestInvalidVersion:
...
@@ -221,3 +226,43 @@ class TestInvalidVersion:
request
.
resolver_match
=
FakeResolverMatch
request
.
resolver_match
=
FakeResolverMatch
response
=
view
(
request
,
version
=
'v3'
)
response
=
view
(
request
,
version
=
'v3'
)
assert
response
.
status_code
==
status
.
HTTP_404_NOT_FOUND
assert
response
.
status_code
==
status
.
HTTP_404_NOT_FOUND
class
TestHyperlinkedRelatedField
(
UsingURLPatterns
,
APITestCase
):
included
=
[
url
(
r'^namespaced/(?P<pk>\d+)/$'
,
mock_view
,
name
=
'namespaced'
),
]
urlpatterns
=
[
url
(
r'^v1/'
,
include
(
included
,
namespace
=
'v1'
)),
url
(
r'^v2/'
,
include
(
included
,
namespace
=
'v2'
))
]
def
setUp
(
self
):
super
(
TestHyperlinkedRelatedField
,
self
)
.
setUp
()
class
HyperlinkedMockQueryset
(
MockQueryset
):
def
get
(
self
,
**
lookup
):
for
item
in
self
.
items
:
if
item
.
pk
==
int
(
lookup
.
get
(
'pk'
,
-
1
)):
return
item
raise
ObjectDoesNotExist
()
self
.
queryset
=
HyperlinkedMockQueryset
([
MockObject
(
pk
=
1
,
name
=
'foo'
),
MockObject
(
pk
=
2
,
name
=
'bar'
),
MockObject
(
pk
=
3
,
name
=
'baz'
)
])
self
.
field
=
serializers
.
HyperlinkedRelatedField
(
view_name
=
'namespaced'
,
queryset
=
self
.
queryset
)
request
=
factory
.
post
(
'/'
,
urlconf
=
'tests.test_versioning'
)
request
.
versioning_scheme
=
NamespaceVersioning
()
request
.
version
=
'v1'
self
.
field
.
_context
=
{
'request'
:
request
}
def
test_bug_2489
(
self
):
self
.
field
.
to_internal_value
(
'/v1/namespaced/3/'
)
with
pytest
.
raises
(
serializers
.
ValidationError
):
self
.
field
.
to_internal_value
(
'/v2/namespaced/3/'
)
tests/utils.py
View file @
65bbc4a1
...
@@ -2,6 +2,30 @@ from django.core.exceptions import ObjectDoesNotExist
...
@@ -2,6 +2,30 @@ from django.core.exceptions import ObjectDoesNotExist
from
django.core.urlresolvers
import
NoReverseMatch
from
django.core.urlresolvers
import
NoReverseMatch
class
UsingURLPatterns
(
object
):
"""
Isolates URL patterns used during testing on the test class itself.
For example:
class MyTestCase(UsingURLPatterns, TestCase):
urlpatterns = [
...
]
def test_something(self):
...
"""
urls
=
__name__
def
setUp
(
self
):
global
urlpatterns
urlpatterns
=
self
.
urlpatterns
def
tearDown
(
self
):
global
urlpatterns
urlpatterns
=
[]
class
MockObject
(
object
):
class
MockObject
(
object
):
def
__init__
(
self
,
**
kwargs
):
def
__init__
(
self
,
**
kwargs
):
self
.
_kwargs
=
kwargs
self
.
_kwargs
=
kwargs
...
...
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