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):
_CONTENTTYPE_PARAM
=
'_content_type'
_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
=
()
@property
def
method
(
self
):
"""
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'
):
self
.
_load_method_and_content_type
()
...
...
@@ -62,6 +70,10 @@ class RequestMixin(object):
def
content_type
(
self
):
"""
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'
):
self
.
_load_method_and_content_type
()
...
...
@@ -71,7 +83,10 @@ class RequestMixin(object):
@property
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'
):
self
.
_load_data_and_files
()
...
...
@@ -81,7 +96,9 @@ class RequestMixin(object):
@property
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'
):
self
.
_load_data_and_files
()
...
...
@@ -205,8 +222,14 @@ class ResponseMixin(object):
_ACCEPT_QUERY_PARAM
=
'_accept'
# Allow override of Accept header in URL query params
_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
=
()
# TODO: wrap this behavior around dispatch(), ensuring it works
# out of the box with existing Django classes that use render_to_response.
def
render
(
self
,
response
):
...
...
@@ -330,14 +353,33 @@ class AuthMixin(object):
"""
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
=
()
"""
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
=
()
@property
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'
):
self
.
_user
=
self
.
_authenticate
()
return
self
.
_user
def
_authenticate
(
self
):
"""
...
...
@@ -351,6 +393,7 @@ class AuthMixin(object):
return
user
return
AnonymousUser
()
# TODO: wrap this behavior around dispatch()
def
_check_permissions
(
self
):
"""
...
...
@@ -359,7 +402,7 @@ class AuthMixin(object):
user
=
self
.
user
for
permission_cls
in
self
.
permissions
:
permission
=
permission_cls
(
self
)
permission
.
check_permission
(
user
)
permission
.
check_permission
(
user
)
########## Resource Mixin ##########
...
...
djangorestframework/parsers.py
View file @
8f6bcac7
...
...
@@ -111,7 +111,8 @@ class PlainTextParser(BaseParser):
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.
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):
"""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.
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'
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
"""
from
django
import
forms
from
django.conf
import
settings
from
django.core.serializers.json
import
DateTimeAwareJSONEncoder
from
django.template
import
RequestContext
,
loader
from
django.utils
import
simplejson
as
json
...
...
@@ -81,7 +82,7 @@ class JSONRenderer(BaseRenderer):
except
(
ValueError
,
TypeError
):
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
):
...
...
djangorestframework/resource.py
→
djangorestframework/resource
s
.py
View file @
8f6bcac7
...
...
@@ -16,9 +16,14 @@ def _model_to_dict(instance, fields=None, exclude=None):
"""
opts
=
instance
.
_meta
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
:
if
not
f
.
editable
:
continue
#
if not f.editable:
#
continue
if
fields
and
not
f
.
name
in
fields
:
continue
if
exclude
and
f
.
name
in
exclude
:
...
...
@@ -27,6 +32,15 @@ def _model_to_dict(instance, fields=None, exclude=None):
data
[
f
.
name
]
=
getattr
(
instance
,
f
.
name
)
else
:
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
...
...
@@ -127,6 +141,8 @@ class Resource(BaseResource):
A (horrible) munging of Piston's pre-serialization. Returns a dict.
"""
return
_object_to_data
(
obj
)
def
_any
(
thing
,
fields
=
()):
"""
Dispatch, all types are routed through here.
...
...
djangorestframework/tests/resource.py
→
djangorestframework/tests/resource
s
.py
View file @
8f6bcac7
"""Tests for the resource module"""
from
django.test
import
TestCase
from
djangorestframework.resource
import
_object_to_data
from
djangorestframework.resource
s
import
_object_to_data
import
datetime
import
decimal
...
...
djangorestframework/views.py
View file @
8f6bcac7
...
...
@@ -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
)]
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
,
{
'detail'
:
'Method
\'
%
s
\'
not allowed on this resource.'
%
self
.
method
})
...
...
@@ -68,56 +69,48 @@ class BaseView(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, View):
# all other authentication is CSRF exempt.
@csrf_exempt
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
try
:
self
.
request
=
request
self
.
args
=
args
self
.
kwargs
=
kwargs
# 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
())
set_script_prefix
(
prefix
)
try
:
# Authenticate and check request is has the relevant permissions
self
.
_check_permissions
()
# Get the appropriate handler method
if
self
.
method
.
lower
()
in
self
.
http_method_names
:
handler
=
getattr
(
self
,
self
.
method
.
lower
(),
self
.
http_method_not_allowed
)
else
:
handler
=
self
.
http_method_not_allowed
response_obj
=
handler
(
request
,
*
args
,
**
kwargs
)
self
.
request
=
request
self
.
args
=
args
self
.
kwargs
=
kwargs
# 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
())
set_script_prefix
(
prefix
)
try
:
# Authenticate and check request is has the relevant permissions
self
.
_check_permissions
()
# Get the appropriate handler method
if
self
.
method
.
lower
()
in
self
.
http_method_names
:
handler
=
getattr
(
self
,
self
.
method
.
lower
(),
self
.
http_method_not_allowed
)
else
:
handler
=
self
.
http_method_not_allowed
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
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
)
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
()
except
ErrorResponse
,
exc
:
response
=
exc
.
response
# 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
)
...
...
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