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
c13c8fe5
Commit
c13c8fe5
authored
Sep 26, 2012
by
Jamie Matthews
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update to new rest_framework package name, simplify implementation
parent
4be937a9
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
103 additions
and
115 deletions
+103
-115
rest_framework/decorators.py
+66
-83
rest_framework/tests/decorators.py
+37
-32
No files found.
rest_framework/decorators.py
View file @
c13c8fe5
...
@@ -6,95 +6,78 @@ from rest_framework import status
...
@@ -6,95 +6,78 @@ from rest_framework import status
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
rest_framework.request
import
Request
from
rest_framework.request
import
Request
from
rest_framework.settings
import
api_settings
from
rest_framework.settings
import
api_settings
from
rest_framwork.views
import
APIView
from
rest_fram
e
work.views
import
APIView
class
LazyViewCreator
(
object
):
def
api_view
(
http_method_names
):
"""
"""
This class is responsible for dynamically creating an APIView subclass that
Decorator that converts a function-based view into an APIView subclass.
will wrap a function-based view. Instances of this class are created
Takes a list of allowed methods for the view as an argument.
by the function-based view decorators (below), and each decorator is
responsible for setting attributes on the instance that will eventually be
copied onto the final class-based view. The CBV gets created lazily the first
time it's needed, and then cached for future use.
This is done so that the ordering of stacked decorators is irrelevant.
"""
"""
def
__init__
(
self
,
wrapped_view
):
def
decorator
(
func
):
self
.
wrapped_view
=
wrapped_view
class
WrappedAPIView
(
APIView
):
pass
# Each item in this dictionary will be copied onto the final
# class-based view that gets created when this object is called
WrappedAPIView
.
http_method_names
=
[
method
.
lower
()
for
method
in
http_method_names
]
self
.
final_view_attrs
=
{
'http_method_names'
:
APIView
.
http_method_names
,
def
handler
(
self
,
*
args
,
**
kwargs
):
'renderer_classes'
:
APIView
.
renderer_classes
,
return
func
(
*
args
,
**
kwargs
)
'parser_classes'
:
APIView
.
parser_classes
,
'authentication_classes'
:
APIView
.
authentication_classes
,
for
method
in
http_method_names
:
'throttle_classes'
:
APIView
.
throttle_classes
,
setattr
(
WrappedAPIView
,
method
.
lower
(),
handler
)
'permission_classes'
:
APIView
.
permission_classes
,
}
WrappedAPIView
.
renderer_classes
=
getattr
(
func
,
'renderer_classes'
,
self
.
_cached_view
=
None
APIView
.
renderer_classes
)
def
handler
(
self
,
*
args
,
**
kwargs
):
WrappedAPIView
.
parser_classes
=
getattr
(
func
,
'parser_classes'
,
return
self
.
wrapped_view
(
*
args
,
**
kwargs
)
APIView
.
parser_classes
)
@property
WrappedAPIView
.
authentication_classes
=
getattr
(
func
,
'authentication_classes'
,
def
view
(
self
):
APIView
.
authentication_classes
)
"""
Accessor for the dynamically created class-based view. This will
WrappedAPIView
.
throttle_classes
=
getattr
(
func
,
'throttle_classes'
,
be created if necessary and cached for next time.
APIView
.
throttle_classes
)
"""
WrappedAPIView
.
permission_classes
=
getattr
(
func
,
'permission_classes'
,
if
self
.
_cached_view
is
None
:
APIView
.
permission_classes
)
class
WrappedAPIView
(
APIView
):
return
WrappedAPIView
.
as_view
()
pass
for
attr
,
value
in
self
.
final_view_attrs
.
items
():
setattr
(
WrappedAPIView
,
attr
,
value
)
# Attach the wrapped view function for each of the
# allowed HTTP methods
for
method
in
WrappedAPIView
.
http_method_names
:
setattr
(
WrappedAPIView
,
method
.
lower
(),
self
.
handler
)
self
.
_cached_view
=
WrappedAPIView
.
as_view
()
return
self
.
_cached_view
def
__call__
(
self
,
*
args
,
**
kwargs
):
"""
This is the actual code that gets run per-request
"""
return
self
.
view
(
*
args
,
**
kwargs
)
@staticmethod
def
maybe_create
(
func_or_instance
):
"""
If the argument is already an instance of LazyViewCreator,
just return it. Otherwise, create a new one.
"""
if
isinstance
(
func_or_instance
,
LazyViewCreator
):
return
func_or_instance
return
LazyViewCreator
(
func_or_instance
)
def
_create_attribute_setting_decorator
(
attribute
,
filter
=
lambda
item
:
item
):
def
decorator
(
value
):
def
inner
(
func
):
wrapper
=
LazyViewCreator
.
maybe_create
(
func
)
wrapper
.
final_view_attrs
[
attribute
]
=
filter
(
value
)
return
wrapper
return
inner
return
decorator
return
decorator
api_view
=
_create_attribute_setting_decorator
(
'http_method_names'
,
filter
=
lambda
methods
:
[
method
.
lower
()
for
method
in
methods
])
def
renderer_classes
(
renderer_classes
):
renderer_classes
=
_create_attribute_setting_decorator
(
'renderer_classes'
)
def
decorator
(
func
):
parser_classes
=
_create_attribute_setting_decorator
(
'parser_classes'
)
setattr
(
func
,
'renderer_classes'
,
renderer_classes
)
authentication_classes
=
_create_attribute_setting_decorator
(
'authentication_classes'
)
return
func
throttle_classes
=
_create_attribute_setting_decorator
(
'throttle_classes'
)
return
decorator
permission_classes
=
_create_attribute_setting_decorator
(
'permission_classes'
)
def
parser_classes
(
parser_classes
):
def
decorator
(
func
):
setattr
(
func
,
'parser_classes'
,
parser_classes
)
return
func
return
decorator
def
authentication_classes
(
authentication_classes
):
def
decorator
(
func
):
setattr
(
func
,
'authentication_classes'
,
authentication_classes
)
return
func
return
decorator
def
throttle_classes
(
throttle_classes
):
def
decorator
(
func
):
setattr
(
func
,
'throttle_classes'
,
throttle_classes
)
return
func
return
decorator
def
permission_classes
(
permission_classes
):
def
decorator
(
func
):
setattr
(
func
,
'permission_classes'
,
permission_classes
)
return
func
return
decorator
djangorest
framework/tests/decorators.py
→
rest_
framework/tests/decorators.py
View file @
c13c8fe5
from
django.test
import
TestCase
from
django.test
import
TestCase
from
djangorestframework.response
import
Response
from
rest_framework.response
import
Response
from
djangorestframework.compat
import
RequestFactory
from
rest_framework.compat
import
RequestFactory
from
djangorestframework.renderers
import
JSONRenderer
from
rest_framework.renderers
import
JSONRenderer
from
djangorestframework.parsers
import
JSONParser
from
rest_framework.parsers
import
JSONParser
from
djangorestframework.authentication
import
BasicAuthentication
from
rest_framework.authentication
import
BasicAuthentication
from
djangorestframework.throttling
import
SimpleRateThottle
from
rest_framework.throttling
import
SimpleRateThottle
from
djangorestframework.permissions
import
IsAuthenticated
from
rest_framework.permissions
import
IsAuthenticated
from
djangorestframework.decorators
import
(
from
rest_framework.views
import
APIView
from
rest_framework.decorators
import
(
api_view
,
api_view
,
renderer_classes
,
renderer_classes
,
parser_classes
,
parser_classes
,
authentication_classes
,
authentication_classes
,
throttle_classes
,
throttle_classes
,
permission_classes
,
permission_classes
,
LazyViewCreator
)
)
...
@@ -22,13 +22,18 @@ class DecoratorTestCase(TestCase):
...
@@ -22,13 +22,18 @@ class DecoratorTestCase(TestCase):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
factory
=
RequestFactory
()
self
.
factory
=
RequestFactory
()
def
_finalize_response
(
self
,
request
,
response
,
*
args
,
**
kwargs
):
print
"HAI"
response
.
request
=
request
return
APIView
.
finalize_response
(
self
,
request
,
response
,
*
args
,
**
kwargs
)
def
test_wrap_view
(
self
):
def
test_wrap_view
(
self
):
@api_view
([
'GET'
])
@api_view
([
'GET'
])
def
view
(
request
):
def
view
(
request
):
return
Response
({})
return
Response
({})
self
.
assertTrue
(
isinstance
(
view
,
LazyViewCreator
))
self
.
assertTrue
(
isinstance
(
view
.
cls_instance
,
APIView
))
def
test_calling_method
(
self
):
def
test_calling_method
(
self
):
...
@@ -46,57 +51,57 @@ class DecoratorTestCase(TestCase):
...
@@ -46,57 +51,57 @@ class DecoratorTestCase(TestCase):
def
test_renderer_classes
(
self
):
def
test_renderer_classes
(
self
):
@renderer_classes
([
JSONRenderer
])
@api_view
([
'GET'
])
@api_view
([
'GET'
])
@renderer_classes
([
JSONRenderer
])
def
view
(
request
):
def
view
(
request
):
return
Response
({})
return
Response
({})
request
=
self
.
factory
.
get
(
'/'
)
request
=
self
.
factory
.
get
(
'/'
)
response
=
view
(
request
)
response
=
view
(
request
)
self
.
assert
Equal
(
response
.
renderer_classes
,
[
JSONRenderer
]
)
self
.
assert
True
(
isinstance
(
response
.
renderer
,
JSONRenderer
)
)
def
test_parser_classes
(
self
):
def
test_parser_classes
(
self
):
@parser_classes
([
JSONParser
])
@api_view
([
'GET'
])
@api_view
([
'GET'
])
@parser_classes
([
JSONParser
])
def
view
(
request
):
def
view
(
request
):
self
.
assertEqual
(
request
.
parser_classes
,
[
JSONParser
])
return
Response
({})
return
Response
({})
request
=
self
.
factory
.
get
(
'/'
)
request
=
self
.
factory
.
get
(
'/'
)
response
=
view
(
request
)
view
(
request
)
self
.
assertEqual
(
response
.
request
.
parser_classes
,
[
JSONParser
])
def
test_authentication_classes
(
self
):
def
test_authentication_classes
(
self
):
@api_view
([
'GET'
])
@authentication_classes
([
BasicAuthentication
])
@authentication_classes
([
BasicAuthentication
])
def
view
(
request
):
self
.
assertEqual
(
request
.
authentication_classes
,
[
BasicAuthentication
])
return
Response
({})
request
=
self
.
factory
.
get
(
'/'
)
view
(
request
)
def
test_permission_classes
(
self
):
@api_view
([
'GET'
])
@api_view
([
'GET'
])
@permission_classes
([
IsAuthenticated
])
def
view
(
request
):
def
view
(
request
):
self
.
assertEqual
(
request
.
permission_classes
,
[
IsAuthenticated
])
return
Response
({})
return
Response
({})
request
=
self
.
factory
.
get
(
'/'
)
request
=
self
.
factory
.
get
(
'/'
)
response
=
view
(
request
)
view
(
request
)
self
.
assertEqual
(
response
.
request
.
authentication_classes
,
[
BasicAuthentication
])
# Doesn't look like th
ese
bits are working quite yet
# Doesn't look like th
is
bits are working quite yet
# def test_throttle_classes(self):
# def test_throttle_classes(self):
#
# @throttle_classes([SimpleRateThottle])
# @api_view(['GET'])
# def view(request):
# return Response({})
#
# request = self.factory.get('/')
# response = view(request)
# self.assertEqual(response.request.throttle, [SimpleRateThottle])
# def test_permission_classes(self):
# @permission_classes([IsAuthenticated])
# @api_view(['GET'])
# @api_view(['GET'])
# @throttle_classes([SimpleRateThottle])
# def view(request):
# def view(request):
# self.assertEqual(request.throttle_classes, [SimpleRateThottle])
# return Response({})
# return Response({})
# request = self.factory.get('/')
# request = self.factory.get('/')
# response = view(request)
# view(request)
# self.assertEqual(response.request.permission_classes, [IsAuthenticated])
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