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
894bf344
Commit
894bf344
authored
May 24, 2011
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tidy up last bits of renderer media type handling
parent
ce6e5fdc
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
59 additions
and
60 deletions
+59
-60
djangorestframework/mixins.py
+15
-10
djangorestframework/response.py
+1
-0
djangorestframework/views.py
+43
-50
No files found.
djangorestframework/mixins.py
View file @
894bf344
...
@@ -243,21 +243,24 @@ class ResponseMixin(object):
...
@@ -243,21 +243,24 @@ class ResponseMixin(object):
self
.
response
=
response
self
.
response
=
response
try
:
try
:
renderer
=
self
.
_determine_renderer
(
self
.
request
)
renderer
,
media_type
=
self
.
_determine_renderer
(
self
.
request
)
except
ErrorResponse
,
exc
:
except
ErrorResponse
,
exc
:
renderer
=
self
.
_default_renderer
(
self
)
renderer
=
self
.
_default_renderer
(
self
)
media_type
=
renderer
.
media_type
response
=
exc
.
response
response
=
exc
.
response
# Set the media type of the response
# Note that the renderer *could* override it in .render() if required.
response
.
media_type
=
renderer
.
media_type
# Serialize the response content
# Serialize the response content
# TODO: renderer.media_type isn't the right thing to do here...
if
response
.
has_content_body
:
if
response
.
has_content_body
:
content
=
renderer
.
render
(
response
.
cleaned_content
,
renderer
.
media_type
)
content
=
renderer
.
render
(
response
.
cleaned_content
,
media_type
)
else
:
else
:
content
=
renderer
.
render
()
content
=
renderer
.
render
()
# Build the HTTP Response
# Build the HTTP Response
# TODO: renderer.media_type isn't the right thing to do here...
resp
=
HttpResponse
(
content
,
mimetype
=
response
.
media_type
,
status
=
response
.
status
)
resp
=
HttpResponse
(
content
,
mimetype
=
renderer
.
media_type
,
status
=
response
.
status
)
for
(
key
,
val
)
in
response
.
headers
.
items
():
for
(
key
,
val
)
in
response
.
headers
.
items
():
resp
[
key
]
=
val
resp
[
key
]
=
val
...
@@ -266,8 +269,10 @@ class ResponseMixin(object):
...
@@ -266,8 +269,10 @@ class ResponseMixin(object):
def
_determine_renderer
(
self
,
request
):
def
_determine_renderer
(
self
,
request
):
"""
"""
Return the appropriate renderer for the output, given the client's 'Accept' header,
Determines the appropriate renderer for the output, given the client's 'Accept' header,
and the content types that this mixin knows how to serve.
and the :attr:`renderers` set on this class.
Returns a 2-tuple of `(renderer, media_type)`
See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
"""
"""
...
@@ -285,19 +290,19 @@ class ResponseMixin(object):
...
@@ -285,19 +290,19 @@ class ResponseMixin(object):
accept_list
=
[
token
.
strip
()
for
token
in
request
.
META
[
"HTTP_ACCEPT"
]
.
split
(
','
)]
accept_list
=
[
token
.
strip
()
for
token
in
request
.
META
[
"HTTP_ACCEPT"
]
.
split
(
','
)]
else
:
else
:
# No accept header specified
# No accept header specified
return
self
.
_default_renderer
(
self
)
return
(
self
.
_default_renderer
(
self
),
self
.
_default_renderer
.
media_type
)
# Check the acceptable media types against each renderer,
# Check the acceptable media types against each renderer,
# attempting more specific media types first
# attempting more specific media types first
# NB. The inner loop here isn't as bad as it first looks :)
# NB. The inner loop here isn't as bad as it first looks :)
# W
e're effectivly looping over max
len(accept_list) * len(self.renderers)
# W
orst case is we're looping over
len(accept_list) * len(self.renderers)
renderers
=
[
renderer_cls
(
self
)
for
renderer_cls
in
self
.
renderers
]
renderers
=
[
renderer_cls
(
self
)
for
renderer_cls
in
self
.
renderers
]
for
media_type_lst
in
order_by_precedence
(
accept_list
):
for
media_type_lst
in
order_by_precedence
(
accept_list
):
for
renderer
in
renderers
:
for
renderer
in
renderers
:
for
media_type
in
media_type_lst
:
for
media_type
in
media_type_lst
:
if
renderer
.
can_handle_response
(
media_type
):
if
renderer
.
can_handle_response
(
media_type
):
return
renderer
return
renderer
,
media_type
# No acceptable renderers were found
# No acceptable renderers were found
raise
ErrorResponse
(
status
.
HTTP_406_NOT_ACCEPTABLE
,
raise
ErrorResponse
(
status
.
HTTP_406_NOT_ACCEPTABLE
,
...
...
djangorestframework/response.py
View file @
894bf344
...
@@ -18,6 +18,7 @@ class Response(object):
...
@@ -18,6 +18,7 @@ class Response(object):
def
__init__
(
self
,
status
=
200
,
content
=
None
,
headers
=
{}):
def
__init__
(
self
,
status
=
200
,
content
=
None
,
headers
=
{}):
self
.
status
=
status
self
.
status
=
status
self
.
media_type
=
None
self
.
has_content_body
=
content
is
not
None
self
.
has_content_body
=
content
is
not
None
self
.
raw_content
=
content
# content prior to filtering
self
.
raw_content
=
content
# content prior to filtering
self
.
cleaned_content
=
content
# content after filtering
self
.
cleaned_content
=
content
# content after filtering
...
...
djangorestframework/views.py
View file @
894bf344
...
@@ -99,59 +99,52 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
...
@@ -99,59 +99,52 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
# 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
):
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
:
try
:
self
.
request
=
request
self
.
initial
(
request
,
*
args
,
**
kwargs
)
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
:
self
.
initial
(
request
,
*
args
,
**
kwargs
)
# Authenticate and check request 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 HttpResponse, Response, or an object, or None
if
isinstance
(
response_obj
,
HttpResponse
):
return
response_obj
elif
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
.
filter_response
(
response
.
raw_content
)
except
ErrorResponse
,
exc
:
# Authenticate and check request has the relevant permissions
response
=
exc
.
response
self
.
_check_permissions
()
# Always add these headers.
# Get the appropriate handler method
#
if
self
.
method
.
lower
()
in
self
.
http_method_names
:
# TODO - this isn't actually the correct way to set the vary header,
handler
=
getattr
(
self
,
self
.
method
.
lower
(),
self
.
http_method_not_allowed
)
# also it's currently sub-obtimal for HTTP caching - need to sort that out.
else
:
response
.
headers
[
'Allow'
]
=
', '
.
join
(
self
.
allowed_methods
)
handler
=
self
.
http_method_not_allowed
response
.
headers
[
'Vary'
]
=
'Authenticate, Accept'
response_obj
=
handler
(
request
,
*
args
,
**
kwargs
)
return
self
.
render
(
response
)
# Allow return value to be either HttpResponse, Response, or an object, or None
except
:
if
isinstance
(
response_obj
,
HttpResponse
):
import
traceback
return
response_obj
traceback
.
print_exc
()
elif
isinstance
(
response_obj
,
Response
):
raise
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
.
filter_response
(
response
.
raw_content
)
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
)
class
ModelView
(
View
):
class
ModelView
(
View
):
...
...
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