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
8f6bcac7
Commit
8f6bcac7
authored
May 13, 2011
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cleanup
parent
44c8b89c
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
115 additions
and
60 deletions
+115
-60
djangorestframework/mixins.py
+47
-4
djangorestframework/parsers.py
+4
-2
djangorestframework/renderers.py
+2
-1
djangorestframework/resources.py
+18
-2
djangorestframework/tests/resources.py
+1
-1
djangorestframework/views.py
+43
-50
No files found.
djangorestframework/mixins.py
View file @
8f6bcac7
...
@@ -46,12 +46,20 @@ class RequestMixin(object):
...
@@ -46,12 +46,20 @@ class RequestMixin(object):
_CONTENTTYPE_PARAM
=
'_content_type'
_CONTENTTYPE_PARAM
=
'_content_type'
_CONTENT_PARAM
=
'_content'
_CONTENT_PARAM
=
'_content'
"""
The set of request parsers that the view can handle.
Should be a tuple/list of classes as described in the ``parsers`` module.
"""
parsers
=
()
parsers
=
()
@property
@property
def
method
(
self
):
def
method
(
self
):
"""
"""
Returns the HTTP method.
Returns the HTTP method.
This should be used instead of ``request.method``, as it allows the method
to be overridden by using a hidden form field on a form POST request.
"""
"""
if
not
hasattr
(
self
,
'_method'
):
if
not
hasattr
(
self
,
'_method'
):
self
.
_load_method_and_content_type
()
self
.
_load_method_and_content_type
()
...
@@ -62,6 +70,10 @@ class RequestMixin(object):
...
@@ -62,6 +70,10 @@ class RequestMixin(object):
def
content_type
(
self
):
def
content_type
(
self
):
"""
"""
Returns the content type header.
Returns the content type header.
This should be used instead of ``request.META.get('HTTP_CONTENT_TYPE')``,
as it allows the content type to be overridden by using a hidden form
field on a form POST request.
"""
"""
if
not
hasattr
(
self
,
'_content_type'
):
if
not
hasattr
(
self
,
'_content_type'
):
self
.
_load_method_and_content_type
()
self
.
_load_method_and_content_type
()
...
@@ -71,7 +83,10 @@ class RequestMixin(object):
...
@@ -71,7 +83,10 @@ class RequestMixin(object):
@property
@property
def
DATA
(
self
):
def
DATA
(
self
):
"""
"""
Returns the request data.
Parses the request body and returns the data.
Similar to ``request.POST``, except that it handles arbitrary parsers,
and also works on methods other than POST (eg PUT).
"""
"""
if
not
hasattr
(
self
,
'_data'
):
if
not
hasattr
(
self
,
'_data'
):
self
.
_load_data_and_files
()
self
.
_load_data_and_files
()
...
@@ -81,7 +96,9 @@ class RequestMixin(object):
...
@@ -81,7 +96,9 @@ class RequestMixin(object):
@property
@property
def
FILES
(
self
):
def
FILES
(
self
):
"""
"""
Returns the request files.
Parses the request body and returns the files.
Similar to request.FILES, except that it handles arbitrary parsers,
and also works on methods other than POST (eg PUT).
"""
"""
if
not
hasattr
(
self
,
'_files'
):
if
not
hasattr
(
self
,
'_files'
):
self
.
_load_data_and_files
()
self
.
_load_data_and_files
()
...
@@ -205,8 +222,14 @@ class ResponseMixin(object):
...
@@ -205,8 +222,14 @@ class ResponseMixin(object):
_ACCEPT_QUERY_PARAM
=
'_accept'
# Allow override of Accept header in URL query params
_ACCEPT_QUERY_PARAM
=
'_accept'
# Allow override of Accept header in URL query params
_IGNORE_IE_ACCEPT_HEADER
=
True
_IGNORE_IE_ACCEPT_HEADER
=
True
"""
The set of response renderers that the view can handle.
Should be a tuple/list of classes as described in the ``renderers`` module.
"""
renderers
=
()
renderers
=
()
# TODO: wrap this behavior around dispatch(), ensuring it works
# TODO: wrap this behavior around dispatch(), ensuring it works
# out of the box with existing Django classes that use render_to_response.
# out of the box with existing Django classes that use render_to_response.
def
render
(
self
,
response
):
def
render
(
self
,
response
):
...
@@ -330,14 +353,33 @@ class AuthMixin(object):
...
@@ -330,14 +353,33 @@ class AuthMixin(object):
"""
"""
Simple mixin class to add authentication and permission checking to a ``View`` class.
Simple mixin class to add authentication and permission checking to a ``View`` class.
"""
"""
"""
The set of authentication types that this view can handle.
Should be a tuple/list of classes as described in the ``authentication`` module.
"""
authentication
=
()
authentication
=
()
"""
The set of permissions that will be enforced on this view.
Should be a tuple/list of classes as described in the ``permissions`` module.
"""
permissions
=
()
permissions
=
()
@property
@property
def
user
(
self
):
def
user
(
self
):
"""
Returns the user for the current request, as determined by the set of
authentication classes applied to the ``View``.
"""
if
not
hasattr
(
self
,
'_user'
):
if
not
hasattr
(
self
,
'_user'
):
self
.
_user
=
self
.
_authenticate
()
self
.
_user
=
self
.
_authenticate
()
return
self
.
_user
return
self
.
_user
def
_authenticate
(
self
):
def
_authenticate
(
self
):
"""
"""
...
@@ -351,6 +393,7 @@ class AuthMixin(object):
...
@@ -351,6 +393,7 @@ class AuthMixin(object):
return
user
return
user
return
AnonymousUser
()
return
AnonymousUser
()
# TODO: wrap this behavior around dispatch()
# TODO: wrap this behavior around dispatch()
def
_check_permissions
(
self
):
def
_check_permissions
(
self
):
"""
"""
...
@@ -359,7 +402,7 @@ class AuthMixin(object):
...
@@ -359,7 +402,7 @@ class AuthMixin(object):
user
=
self
.
user
user
=
self
.
user
for
permission_cls
in
self
.
permissions
:
for
permission_cls
in
self
.
permissions
:
permission
=
permission_cls
(
self
)
permission
=
permission_cls
(
self
)
permission
.
check_permission
(
user
)
permission
.
check_permission
(
user
)
########## Resource Mixin ##########
########## Resource Mixin ##########
...
...
djangorestframework/parsers.py
View file @
8f6bcac7
...
@@ -111,7 +111,8 @@ class PlainTextParser(BaseParser):
...
@@ -111,7 +111,8 @@ class PlainTextParser(BaseParser):
class
FormParser
(
BaseParser
,
DataFlatener
):
class
FormParser
(
BaseParser
,
DataFlatener
):
"""The default parser for form data.
"""
The default parser for form data.
Return a dict containing a single value for each non-reserved parameter.
Return a dict containing a single value for each non-reserved parameter.
In order to handle select multiple (and having possibly more than a single value for each parameter),
In order to handle select multiple (and having possibly more than a single value for each parameter),
...
@@ -122,7 +123,8 @@ class FormParser(BaseParser, DataFlatener):
...
@@ -122,7 +123,8 @@ class FormParser(BaseParser, DataFlatener):
"""The value of the parameter when the select multiple is empty.
"""The value of the parameter when the select multiple is empty.
Browsers are usually stripping the select multiple that have no option selected from the parameters sent.
Browsers are usually stripping the select multiple that have no option selected from the parameters sent.
A common hack to avoid this is to send the parameter with a value specifying that the list is empty.
A common hack to avoid this is to send the parameter with a value specifying that the list is empty.
This value will always be stripped before the data is returned."""
This value will always be stripped before the data is returned.
"""
EMPTY_VALUE
=
'_empty'
EMPTY_VALUE
=
'_empty'
RESERVED_FORM_PARAMS
=
(
'csrfmiddlewaretoken'
,)
RESERVED_FORM_PARAMS
=
(
'csrfmiddlewaretoken'
,)
...
...
djangorestframework/renderers.py
View file @
8f6bcac7
...
@@ -7,6 +7,7 @@ and providing forms and links depending on the allowed methods, renderers and pa
...
@@ -7,6 +7,7 @@ and providing forms and links depending on the allowed methods, renderers and pa
"""
"""
from
django
import
forms
from
django
import
forms
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.serializers.json
import
DateTimeAwareJSONEncoder
from
django.template
import
RequestContext
,
loader
from
django.template
import
RequestContext
,
loader
from
django.utils
import
simplejson
as
json
from
django.utils
import
simplejson
as
json
...
@@ -81,7 +82,7 @@ class JSONRenderer(BaseRenderer):
...
@@ -81,7 +82,7 @@ class JSONRenderer(BaseRenderer):
except
(
ValueError
,
TypeError
):
except
(
ValueError
,
TypeError
):
indent
=
None
indent
=
None
return
json
.
dumps
(
obj
,
indent
=
indent
,
sort_keys
=
sort_keys
)
return
json
.
dumps
(
obj
,
cls
=
DateTimeAwareJSONEncoder
,
indent
=
indent
,
sort_keys
=
sort_keys
)
class
XMLRenderer
(
BaseRenderer
):
class
XMLRenderer
(
BaseRenderer
):
...
...
djangorestframework/resource.py
→
djangorestframework/resource
s
.py
View file @
8f6bcac7
...
@@ -16,9 +16,14 @@ def _model_to_dict(instance, fields=None, exclude=None):
...
@@ -16,9 +16,14 @@ def _model_to_dict(instance, fields=None, exclude=None):
"""
"""
opts
=
instance
.
_meta
opts
=
instance
.
_meta
data
=
{}
data
=
{}
#print [rel.name for rel in opts.get_all_related_objects()]
#related = [rel.get_accessor_name() for rel in opts.get_all_related_objects()]
#print [getattr(instance, rel) for rel in related]
for
f
in
opts
.
fields
+
opts
.
many_to_many
:
for
f
in
opts
.
fields
+
opts
.
many_to_many
:
if
not
f
.
editable
:
#
if not f.editable:
continue
#
continue
if
fields
and
not
f
.
name
in
fields
:
if
fields
and
not
f
.
name
in
fields
:
continue
continue
if
exclude
and
f
.
name
in
exclude
:
if
exclude
and
f
.
name
in
exclude
:
...
@@ -27,6 +32,15 @@ def _model_to_dict(instance, fields=None, exclude=None):
...
@@ -27,6 +32,15 @@ def _model_to_dict(instance, fields=None, exclude=None):
data
[
f
.
name
]
=
getattr
(
instance
,
f
.
name
)
data
[
f
.
name
]
=
getattr
(
instance
,
f
.
name
)
else
:
else
:
data
[
f
.
name
]
=
f
.
value_from_object
(
instance
)
data
[
f
.
name
]
=
f
.
value_from_object
(
instance
)
#print fields - (opts.fields + opts.many_to_many)
#for related in [rel.get_accessor_name() for rel in opts.get_all_related_objects()]:
# if fields and not related in fields:
# continue
# if exclude and related in exclude:
# continue
# data[related] = getattr(instance, related)
return
data
return
data
...
@@ -127,6 +141,8 @@ class Resource(BaseResource):
...
@@ -127,6 +141,8 @@ class Resource(BaseResource):
A (horrible) munging of Piston's pre-serialization. Returns a dict.
A (horrible) munging of Piston's pre-serialization. Returns a dict.
"""
"""
return
_object_to_data
(
obj
)
def
_any
(
thing
,
fields
=
()):
def
_any
(
thing
,
fields
=
()):
"""
"""
Dispatch, all types are routed through here.
Dispatch, all types are routed through here.
...
...
djangorestframework/tests/resource.py
→
djangorestframework/tests/resource
s
.py
View file @
8f6bcac7
"""Tests for the resource module"""
"""Tests for the resource module"""
from
django.test
import
TestCase
from
django.test
import
TestCase
from
djangorestframework.resource
import
_object_to_data
from
djangorestframework.resource
s
import
_object_to_data
import
datetime
import
datetime
import
decimal
import
decimal
...
...
djangorestframework/views.py
View file @
8f6bcac7
...
@@ -56,9 +56,10 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
...
@@ -56,9 +56,10 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
"""
"""
return
[
method
.
upper
()
for
method
in
self
.
http_method_names
if
hasattr
(
self
,
method
)]
return
[
method
.
upper
()
for
method
in
self
.
http_method_names
if
hasattr
(
self
,
method
)]
def
http_method_not_allowed
(
self
,
request
,
*
args
,
**
kwargs
):
def
http_method_not_allowed
(
self
,
request
,
*
args
,
**
kwargs
):
"""
"""
Return an HTTP 405 error if an operation is called which does not have a handler method.
Return an HTTP 405 error if an operation is called which does not have a handler method.
"""
"""
raise
ErrorResponse
(
status
.
HTTP_405_METHOD_NOT_ALLOWED
,
raise
ErrorResponse
(
status
.
HTTP_405_METHOD_NOT_ALLOWED
,
{
'detail'
:
'Method
\'
%
s
\'
not allowed on this resource.'
%
self
.
method
})
{
'detail'
:
'Method
\'
%
s
\'
not allowed on this resource.'
%
self
.
method
})
...
@@ -68,56 +69,48 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
...
@@ -68,56 +69,48 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
# all other authentication is CSRF exempt.
# all other authentication is CSRF exempt.
@csrf_exempt
@csrf_exempt
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
try
:
self
.
request
=
request
self
.
request
=
request
self
.
args
=
args
self
.
args
=
args
self
.
kwargs
=
kwargs
self
.
kwargs
=
kwargs
# Calls to 'reverse' will not be fully qualified unless we set the scheme/host/port here.
# Calls to 'reverse' will not be fully qualified unless we set the scheme/host/port here.
prefix
=
'
%
s://
%
s'
%
(
request
.
is_secure
()
and
'https'
or
'http'
,
request
.
get_host
())
prefix
=
'
%
s://
%
s'
%
(
request
.
is_secure
()
and
'https'
or
'http'
,
request
.
get_host
())
set_script_prefix
(
prefix
)
set_script_prefix
(
prefix
)
try
:
try
:
# Authenticate and check request is has the relevant permissions
# Authenticate and check request is has the relevant permissions
self
.
_check_permissions
()
self
.
_check_permissions
()
# Get the appropriate handler method
# Get the appropriate handler method
if
self
.
method
.
lower
()
in
self
.
http_method_names
:
if
self
.
method
.
lower
()
in
self
.
http_method_names
:
handler
=
getattr
(
self
,
self
.
method
.
lower
(),
self
.
http_method_not_allowed
)
handler
=
getattr
(
self
,
self
.
method
.
lower
(),
self
.
http_method_not_allowed
)
else
:
else
:
handler
=
self
.
http_method_not_allowed
handler
=
self
.
http_method_not_allowed
response_obj
=
handler
(
request
,
*
args
,
**
kwargs
)
response_obj
=
handler
(
request
,
*
args
,
**
kwargs
)
# Allow return value to be either Response, or an object, or None
if
isinstance
(
response_obj
,
Response
):
response
=
response_obj
elif
response_obj
is
not
None
:
response
=
Response
(
status
.
HTTP_200_OK
,
response_obj
)
else
:
response
=
Response
(
status
.
HTTP_204_NO_CONTENT
)
# Pre-serialize filtering (eg filter complex objects into natively serializable types)
response
.
cleaned_content
=
self
.
object_to_data
(
response
.
raw_content
)
# Allow return value to be either Response, or an object, or None
except
ErrorResponse
,
exc
:
if
isinstance
(
response_obj
,
Response
):
response
=
exc
.
response
response
=
response_obj
elif
response_obj
is
not
None
:
# Always add these headers.
response
=
Response
(
status
.
HTTP_200_OK
,
response_obj
)
#
else
:
# TODO - this isn't actually the correct way to set the vary header,
response
=
Response
(
status
.
HTTP_204_NO_CONTENT
)
# also it's currently sub-obtimal for HTTP caching - need to sort that out.
response
.
headers
[
'Allow'
]
=
', '
.
join
(
self
.
allowed_methods
)
# Pre-serialize filtering (eg filter complex objects into natively serializable types)
response
.
headers
[
'Vary'
]
=
'Authenticate, Accept'
response
.
cleaned_content
=
self
.
object_to_data
(
response
.
raw_content
)
return
self
.
render
(
response
)
except
ErrorResponse
,
exc
:
response
=
exc
.
response
except
:
import
traceback
traceback
.
print_exc
()
raise
# Always add these headers.
#
# TODO - this isn't actually the correct way to set the vary header,
# also it's currently sub-obtimal for HTTP caching - need to sort that out.
response
.
headers
[
'Allow'
]
=
', '
.
join
(
self
.
allowed_methods
)
response
.
headers
[
'Vary'
]
=
'Authenticate, Accept'
return
self
.
render
(
response
)
except
:
import
traceback
traceback
.
print_exc
()
...
...
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