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
527e4ffd
Commit
527e4ffd
authored
May 10, 2011
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
renderer API work
parent
8f58ee48
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
222 additions
and
120 deletions
+222
-120
djangorestframework/mixins.py
+11
-9
djangorestframework/renderers.py
+81
-48
djangorestframework/tests/renderers.py
+38
-8
djangorestframework/utils/__init__.py
+12
-2
djangorestframework/utils/mediatypes.py
+25
-4
djangorestframework/views.py
+55
-49
No files found.
djangorestframework/mixins.py
View file @
527e4ffd
...
@@ -17,14 +17,16 @@ import re
...
@@ -17,14 +17,16 @@ import re
from
StringIO
import
StringIO
from
StringIO
import
StringIO
__all__
=
(
'RequestMixin'
,
__all__
=
(
'ResponseMixin'
,
'RequestMixin'
,
'AuthMixin'
,
'ResponseMixin'
,
'ReadModelMixin'
,
'AuthMixin'
,
'CreateModelMixin'
,
'ReadModelMixin'
,
'UpdateModelMixin'
,
'CreateModelMixin'
,
'DeleteModelMixin'
,
'UpdateModelMixin'
,
'ListModelMixin'
)
'DeleteModelMixin'
,
'ListModelMixin'
)
########## Request Mixin ##########
########## Request Mixin ##########
...
@@ -267,7 +269,7 @@ class ResponseMixin(object):
...
@@ -267,7 +269,7 @@ class ResponseMixin(object):
# Serialize the response content
# Serialize the response content
if
response
.
has_content_body
:
if
response
.
has_content_body
:
content
=
renderer
(
self
)
.
render
(
output
=
response
.
cleaned_content
)
content
=
renderer
(
self
)
.
render
(
response
.
cleaned_content
,
renderer
.
media_type
)
else
:
else
:
content
=
renderer
(
self
)
.
render
()
content
=
renderer
(
self
)
.
render
()
...
...
djangorestframework/renderers.py
View file @
527e4ffd
"""Renderers are used to serialize a View's output into specific media types.
"""
Renderers are used to serialize a View's output into specific media types.
django-rest-framework also provides HTML and PlainText renderers that help self-document the API,
django-rest-framework also provides HTML and PlainText renderers that help self-document the API,
by serializing the output along with documentation regarding the Resource, output status and headers,
by serializing the output along with documentation regarding the Resource, output status and headers,
and providing forms and links depending on the allowed methods, renderers and parsers on the Resource.
and providing forms and links depending on the allowed methods, renderers and parsers on the Resource.
...
@@ -7,64 +8,78 @@ from django import forms
...
@@ -7,64 +8,78 @@ from django import forms
from
django.conf
import
settings
from
django.conf
import
settings
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
from
django
import
forms
from
djangorestframework
.utils
import
dict2xml
,
url_resolve
s
from
djangorestframework
import
statu
s
from
djangorestframework.compat
import
apply_markdown
from
djangorestframework.compat
import
apply_markdown
from
djangorestframework.utils
import
dict2xml
,
url_resolves
from
djangorestframework.utils.breadcrumbs
import
get_breadcrumbs
from
djangorestframework.utils.breadcrumbs
import
get_breadcrumbs
from
djangorestframework.utils.description
import
get_name
,
get_description
from
djangorestframework.utils.description
import
get_name
,
get_description
from
djangorestframework
import
status
from
djangorestframework
.utils.mediatypes
import
get_media_type_params
,
add_media_type_param
from
urllib
import
quote_plus
import
string
import
re
from
decimal
import
Decimal
from
decimal
import
Decimal
import
re
import
string
from
urllib
import
quote_plus
__all__
=
(
'BaseRenderer'
,
'JSONRenderer'
,
'DocumentingHTMLRenderer'
,
'DocumentingXHTMLRenderer'
,
'DocumentingPlainTextRenderer'
,
'XMLRenderer'
)
# TODO: Rename verbose to something more appropriate
# TODO: Maybe None could be handled more cleanly. It'd be nice if it was handled by default,
# and only have an renderer output anything if it explicitly provides support for that.
class
BaseRenderer
(
object
):
class
BaseRenderer
(
object
):
"""All renderers must extend this class, set the media_type attribute, and
"""
override the render() function."""
All renderers must extend this class, set the media_type attribute, and
override the render() function.
"""
media_type
=
None
media_type
=
None
def
__init__
(
self
,
view
):
def
__init__
(
self
,
view
):
self
.
view
=
view
self
.
view
=
view
def
render
(
self
,
output
=
None
,
verbose
=
False
):
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
"""By default render simply returns the ouput as-is.
"""
Override this method to provide for other behaviour."""
By default render simply returns the ouput as-is.
if
output
is
None
:
Override this method to provide for other behavior.
"""
if
obj
is
None
:
return
''
return
''
return
o
utput
return
o
bj
class
TemplateRenderer
(
BaseRenderer
):
class
TemplateRenderer
(
BaseRenderer
):
"""A Base class provided for convenience.
"""
A Base class provided for convenience.
Render the o
utpu
t simply by using the given template.
Render the o
bjec
t simply by using the given template.
To create a template renderer, subclass this, and set
To create a template renderer, subclass this, and set
the ``media_type`` and ``template`` attributes"""
the ``media_type`` and ``template`` attributes
"""
media_type
=
None
media_type
=
None
template
=
None
template
=
None
def
render
(
self
,
o
utput
=
None
,
verbose
=
Fals
e
):
def
render
(
self
,
o
bj
=
None
,
media_type
=
Non
e
):
if
o
utput
is
None
:
if
o
bj
is
None
:
return
''
return
''
context
=
RequestContext
(
self
.
request
,
o
utput
)
context
=
RequestContext
(
self
.
request
,
o
bj
)
return
self
.
template
.
render
(
context
)
return
self
.
template
.
render
(
context
)
class
DocumentingTemplateRenderer
(
BaseRenderer
):
class
DocumentingTemplateRenderer
(
BaseRenderer
):
"""Base class for renderers used to self-document the API.
"""
Implementing classes should extend this class and set the template attribute."""
Base class for renderers used to self-document the API.
Implementing classes should extend this class and set the template attribute.
"""
template
=
None
template
=
None
def
_get_content
(
self
,
resource
,
request
,
o
utput
):
def
_get_content
(
self
,
resource
,
request
,
o
bj
,
media_type
):
"""Get the content as if it had been render
t
ed by a non-documenting renderer.
"""Get the content as if it had been rendered by a non-documenting renderer.
(Typically this will be the content as it would have been if the Resource had been
(Typically this will be the content as it would have been if the Resource had been
requested with an 'Accept: */*' header, although with verbose style formatting if appropriate.)"""
requested with an 'Accept: */*' header, although with verbose style formatting if appropriate.)"""
...
@@ -73,8 +88,9 @@ class DocumentingTemplateRenderer(BaseRenderer):
...
@@ -73,8 +88,9 @@ class DocumentingTemplateRenderer(BaseRenderer):
renderers
=
[
renderer
for
renderer
in
resource
.
renderers
if
not
isinstance
(
renderer
,
DocumentingTemplateRenderer
)]
renderers
=
[
renderer
for
renderer
in
resource
.
renderers
if
not
isinstance
(
renderer
,
DocumentingTemplateRenderer
)]
if
not
renderers
:
if
not
renderers
:
return
'[No renderers were found]'
return
'[No renderers were found]'
content
=
renderers
[
0
](
resource
)
.
render
(
output
,
verbose
=
True
)
media_type
=
add_media_type_param
(
media_type
,
'indent'
,
'4'
)
content
=
renderers
[
0
](
resource
)
.
render
(
obj
,
media_type
)
if
not
all
(
char
in
string
.
printable
for
char
in
content
):
if
not
all
(
char
in
string
.
printable
for
char
in
content
):
return
'[
%
d bytes of binary content]'
return
'[
%
d bytes of binary content]'
...
@@ -149,8 +165,8 @@ class DocumentingTemplateRenderer(BaseRenderer):
...
@@ -149,8 +165,8 @@ class DocumentingTemplateRenderer(BaseRenderer):
return
GenericContentForm
(
resource
)
return
GenericContentForm
(
resource
)
def
render
(
self
,
o
utput
=
None
):
def
render
(
self
,
o
bj
=
None
,
media_type
=
None
):
content
=
self
.
_get_content
(
self
.
view
,
self
.
view
.
request
,
o
utput
)
content
=
self
.
_get_content
(
self
.
view
,
self
.
view
.
request
,
o
bj
,
media_type
)
form_instance
=
self
.
_get_form_instance
(
self
.
view
)
form_instance
=
self
.
_get_form_instance
(
self
.
view
)
if
url_resolves
(
settings
.
LOGIN_URL
)
and
url_resolves
(
settings
.
LOGOUT_URL
):
if
url_resolves
(
settings
.
LOGIN_URL
)
and
url_resolves
(
settings
.
LOGOUT_URL
):
...
@@ -194,46 +210,63 @@ class DocumentingTemplateRenderer(BaseRenderer):
...
@@ -194,46 +210,63 @@ class DocumentingTemplateRenderer(BaseRenderer):
class
JSONRenderer
(
BaseRenderer
):
class
JSONRenderer
(
BaseRenderer
):
"""Renderer which serializes to JSON"""
"""
Renderer which serializes to JSON
"""
media_type
=
'application/json'
media_type
=
'application/json'
def
render
(
self
,
o
utput
=
None
,
verbose
=
Fals
e
):
def
render
(
self
,
o
bj
=
None
,
media_type
=
Non
e
):
if
o
utput
is
None
:
if
o
bj
is
None
:
return
''
return
''
if
verbose
:
return
json
.
dumps
(
output
,
indent
=
4
,
sort_keys
=
True
)
indent
=
get_media_type_params
(
media_type
)
.
get
(
'indent'
,
None
)
return
json
.
dumps
(
output
)
if
indent
is
not
None
:
try
:
indent
=
int
(
indent
)
except
ValueError
:
indent
=
None
sort_keys
=
indent
and
True
or
False
return
json
.
dumps
(
obj
,
indent
=
indent
,
sort_keys
=
sort_keys
)
class
XMLRenderer
(
BaseRenderer
):
class
XMLRenderer
(
BaseRenderer
):
"""Renderer which serializes to XML."""
"""
Renderer which serializes to XML.
"""
media_type
=
'application/xml'
media_type
=
'application/xml'
def
render
(
self
,
o
utput
=
None
,
verbose
=
Fals
e
):
def
render
(
self
,
o
bj
=
None
,
media_type
=
Non
e
):
if
o
utput
is
None
:
if
o
bj
is
None
:
return
''
return
''
return
dict2xml
(
o
utput
)
return
dict2xml
(
o
bj
)
class
DocumentingHTMLRenderer
(
DocumentingTemplateRenderer
):
class
DocumentingHTMLRenderer
(
DocumentingTemplateRenderer
):
"""Renderer which provides a browsable HTML interface for an API.
"""
See the examples listed in the django-rest-framework documentation to see this in actions."""
Renderer which provides a browsable HTML interface for an API.
See the examples at http://api.django-rest-framework.org to see this in action.
"""
media_type
=
'text/html'
media_type
=
'text/html'
template
=
'renderer.html'
template
=
'renderer.html'
class
DocumentingXHTMLRenderer
(
DocumentingTemplateRenderer
):
class
DocumentingXHTMLRenderer
(
DocumentingTemplateRenderer
):
"""Identical to DocumentingHTMLRenderer, except with an xhtml media type.
"""
Identical to DocumentingHTMLRenderer, except with an xhtml media type.
We need this to be listed in preference to xml in order to return HTML to WebKit based browsers,
We need this to be listed in preference to xml in order to return HTML to WebKit based browsers,
given their Accept headers."""
given their Accept headers.
"""
media_type
=
'application/xhtml+xml'
media_type
=
'application/xhtml+xml'
template
=
'renderer.html'
template
=
'renderer.html'
class
DocumentingPlainTextRenderer
(
DocumentingTemplateRenderer
):
class
DocumentingPlainTextRenderer
(
DocumentingTemplateRenderer
):
"""Renderer that serializes the output with the default renderer, but also provides plain-text
"""
doumentation of the returned status and headers, and of the resource's name and description.
Renderer that serializes the object with the default renderer, but also provides plain-text
Useful for browsing an API with command line tools."""
documentation of the returned status and headers, and of the resource's name and description.
Useful for browsing an API with command line tools.
"""
media_type
=
'text/plain'
media_type
=
'text/plain'
template
=
'renderer.txt'
template
=
'renderer.txt'
...
...
djangorestframework/tests/renderers.py
View file @
527e4ffd
...
@@ -2,9 +2,10 @@ from django.conf.urls.defaults import patterns, url
...
@@ -2,9 +2,10 @@ from django.conf.urls.defaults import patterns, url
from
django
import
http
from
django
import
http
from
django.test
import
TestCase
from
django.test
import
TestCase
from
djangorestframework.compat
import
View
from
djangorestframework.compat
import
View
from
djangorestframework.renderers
import
BaseRenderer
from
djangorestframework.renderers
import
BaseRenderer
,
JSONRenderer
from
djangorestframework.mixins
import
ResponseMixin
from
djangorestframework.mixins
import
ResponseMixin
from
djangorestframework.response
import
Response
from
djangorestframework.response
import
Response
from
djangorestframework.utils.mediatypes
import
add_media_type_param
DUMMYSTATUS
=
200
DUMMYSTATUS
=
200
DUMMYCONTENT
=
'dummycontent'
DUMMYCONTENT
=
'dummycontent'
...
@@ -20,14 +21,14 @@ class MockView(ResponseMixin, View):
...
@@ -20,14 +21,14 @@ class MockView(ResponseMixin, View):
class
RendererA
(
BaseRenderer
):
class
RendererA
(
BaseRenderer
):
media_type
=
'mock/renderera'
media_type
=
'mock/renderera'
def
render
(
self
,
o
utput
,
verbose
=
Fals
e
):
def
render
(
self
,
o
bj
=
None
,
content_type
=
Non
e
):
return
RENDERER_A_SERIALIZER
(
o
utput
)
return
RENDERER_A_SERIALIZER
(
o
bj
)
class
RendererB
(
BaseRenderer
):
class
RendererB
(
BaseRenderer
):
media_type
=
'mock/rendererb'
media_type
=
'mock/rendererb'
def
render
(
self
,
o
utput
,
verbose
=
Fals
e
):
def
render
(
self
,
o
bj
=
None
,
content_type
=
Non
e
):
return
RENDERER_B_SERIALIZER
(
o
utput
)
return
RENDERER_B_SERIALIZER
(
o
bj
)
urlpatterns
=
patterns
(
''
,
urlpatterns
=
patterns
(
''
,
...
@@ -36,7 +37,9 @@ urlpatterns = patterns('',
...
@@ -36,7 +37,9 @@ urlpatterns = patterns('',
class
RendererIntegrationTests
(
TestCase
):
class
RendererIntegrationTests
(
TestCase
):
"""End-to-end testing of renderers using an RendererMixin on a generic view."""
"""
End-to-end testing of renderers using an RendererMixin on a generic view.
"""
urls
=
'djangorestframework.tests.renderers'
urls
=
'djangorestframework.tests.renderers'
...
@@ -73,4 +76,32 @@ class RendererIntegrationTests(TestCase):
...
@@ -73,4 +76,32 @@ class RendererIntegrationTests(TestCase):
def
test_unsatisfiable_accept_header_on_request_returns_406_status
(
self
):
def
test_unsatisfiable_accept_header_on_request_returns_406_status
(
self
):
"""If the Accept header is unsatisfiable we should return a 406 Not Acceptable response."""
"""If the Accept header is unsatisfiable we should return a 406 Not Acceptable response."""
resp
=
self
.
client
.
get
(
'/'
,
HTTP_ACCEPT
=
'foo/bar'
)
resp
=
self
.
client
.
get
(
'/'
,
HTTP_ACCEPT
=
'foo/bar'
)
self
.
assertEquals
(
resp
.
status_code
,
406
)
self
.
assertEquals
(
resp
.
status_code
,
406
)
\ No newline at end of file
_flat_repr
=
'{"foo": ["bar", "baz"]}'
_indented_repr
=
"""{
"foo": [
"bar",
"baz"
]
}"""
class
JSONRendererTests
(
TestCase
):
"""
Tests specific to the JSON Renderer
"""
def
test_without_content_type_args
(
self
):
obj
=
{
'foo'
:[
'bar'
,
'baz'
]}
renderer
=
JSONRenderer
(
None
)
content
=
renderer
.
render
(
obj
,
'application/json'
)
self
.
assertEquals
(
content
,
_flat_repr
)
def
test_with_content_type_args
(
self
):
obj
=
{
'foo'
:[
'bar'
,
'baz'
]}
renderer
=
JSONRenderer
(
None
)
content
=
renderer
.
render
(
obj
,
'application/json; indent=2'
)
self
.
assertEquals
(
content
,
_indented_repr
)
djangorestframework/utils/__init__.py
View file @
527e4ffd
...
@@ -16,7 +16,15 @@ import xml.etree.ElementTree as ET
...
@@ -16,7 +16,15 @@ import xml.etree.ElementTree as ET
MSIE_USER_AGENT_REGEX
=
re
.
compile
(
r'^Mozilla/[0-9]+\.[0-9]+ \([^)]*; MSIE [0-9]+\.[0-9]+[a-z]?;[^)]*\)(?!.* Opera )'
)
MSIE_USER_AGENT_REGEX
=
re
.
compile
(
r'^Mozilla/[0-9]+\.[0-9]+ \([^)]*; MSIE [0-9]+\.[0-9]+[a-z]?;[^)]*\)(?!.* Opera )'
)
def
as_tuple
(
obj
):
def
as_tuple
(
obj
):
"""Given obj return a tuple"""
"""
Given an object which may be a list/tuple, another object, or None,
return that object in list form.
IE:
If the object is already a list/tuple just return it.
If the object is not None, return it in a list with a single element.
If the object is None return an empty list.
"""
if
obj
is
None
:
if
obj
is
None
:
return
()
return
()
elif
isinstance
(
obj
,
list
):
elif
isinstance
(
obj
,
list
):
...
@@ -27,7 +35,9 @@ def as_tuple(obj):
...
@@ -27,7 +35,9 @@ def as_tuple(obj):
def
url_resolves
(
url
):
def
url_resolves
(
url
):
"""Return True if the given URL is mapped to a view in the urlconf, False otherwise."""
"""
Return True if the given URL is mapped to a view in the urlconf, False otherwise.
"""
try
:
try
:
resolve
(
url
)
resolve
(
url
)
except
:
except
:
...
...
djangorestframework/utils/mediatypes.py
View file @
527e4ffd
...
@@ -15,7 +15,7 @@ def media_type_matches(lhs, rhs):
...
@@ -15,7 +15,7 @@ def media_type_matches(lhs, rhs):
Valid media type strings include:
Valid media type strings include:
'application/json indent=4'
'application/json
;
indent=4'
'application/json'
'application/json'
'text/*'
'text/*'
'*/*'
'*/*'
...
@@ -33,10 +33,28 @@ def is_form_media_type(media_type):
...
@@ -33,10 +33,28 @@ def is_form_media_type(media_type):
media_type
=
_MediaType
(
media_type
)
media_type
=
_MediaType
(
media_type
)
return
media_type
.
full_type
==
'application/x-www-form-urlencoded'
or
\
return
media_type
.
full_type
==
'application/x-www-form-urlencoded'
or
\
media_type
.
full_type
==
'multipart/form-data'
media_type
.
full_type
==
'multipart/form-data'
def
add_media_type_param
(
media_type
,
key
,
val
):
"""
Add a key, value parameter to a media type string, and return the new media type string.
"""
media_type
=
_MediaType
(
media_type
)
media_type
.
params
[
key
]
=
val
return
str
(
media_type
)
def
get_media_type_params
(
media_type
):
"""
Return a dictionary of the parameters on the given media type.
"""
return
_MediaType
(
media_type
)
.
params
class
_MediaType
(
object
):
class
_MediaType
(
object
):
def
__init__
(
self
,
media_type_str
):
def
__init__
(
self
,
media_type_str
):
if
media_type_str
is
None
:
media_type_str
=
''
self
.
orig
=
media_type_str
self
.
orig
=
media_type_str
self
.
full_type
,
self
.
params
=
parse_header
(
media_type_str
)
self
.
full_type
,
self
.
params
=
parse_header
(
media_type_str
)
self
.
main_type
,
sep
,
self
.
sub_type
=
self
.
full_type
.
partition
(
'/'
)
self
.
main_type
,
sep
,
self
.
sub_type
=
self
.
full_type
.
partition
(
'/'
)
...
@@ -94,5 +112,8 @@ class _MediaType(object):
...
@@ -94,5 +112,8 @@ class _MediaType(object):
return
unicode
(
self
)
.
encode
(
'utf-8'
)
return
unicode
(
self
)
.
encode
(
'utf-8'
)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
self
.
orig
ret
=
"
%
s/
%
s"
%
(
self
.
main_type
,
self
.
sub_type
)
for
key
,
val
in
self
.
params
.
items
():
ret
+=
";
%
s=
%
s"
%
(
key
,
val
)
return
ret
djangorestframework/views.py
View file @
527e4ffd
...
@@ -7,11 +7,13 @@ from djangorestframework.mixins import *
...
@@ -7,11 +7,13 @@ from djangorestframework.mixins import *
from
djangorestframework
import
resource
,
renderers
,
parsers
,
authentication
,
permissions
,
validators
,
status
from
djangorestframework
import
resource
,
renderers
,
parsers
,
authentication
,
permissions
,
validators
,
status
__all__
=
(
'BaseView'
,
__all__
=
(
'ModelView'
,
'BaseView'
,
'InstanceModelView'
,
'ModelView'
,
'ListOrModelView'
,
'InstanceModelView'
,
'ListOrCreateModelView'
)
'ListOrModelView'
,
'ListOrCreateModelView'
)
...
@@ -78,55 +80,59 @@ class BaseView(RequestMixin, ResponseMixin, AuthMixin, View):
...
@@ -78,55 +80,59 @@ class BaseView(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
):
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
:
# If using a form POST with '_method'/'_content'/'_content_type' overrides, then alter
self
.
request
=
request
# self.method, self.content_type, self.RAW_CONTENT & self.CONTENT appropriately.
self
.
args
=
args
self
.
perform_form_overloading
()
self
.
kwargs
=
kwargs
# Authenticate and check request is has the relevant permissions
# Calls to 'reverse' will not be fully qualified unless we set the scheme/host/port here.
self
.
_check_permissions
()
prefix
=
'
%
s://
%
s'
%
(
request
.
is_secure
()
and
'https'
or
'http'
,
request
.
get_host
())
set_script_prefix
(
prefix
)
# Get the appropriate handler method
if
self
.
method
.
lower
()
in
self
.
http_method_names
:
try
:
handler
=
getattr
(
self
,
self
.
method
.
lower
(),
self
.
http_method_not_allowed
)
# If using a form POST with '_method'/'_content'/'_content_type' overrides, then alter
else
:
# self.method, self.content_type, self.RAW_CONTENT & self.CONTENT appropriately.
handler
=
self
.
http_method_not_allowed
self
.
perform_form_overloading
()
response_obj
=
handler
(
request
,
*
args
,
**
kwargs
)
# Authenticate and check request is has the relevant permissions
self
.
_check_permissions
()
# Allow return value to be either Response, or an object, or None
if
isinstance
(
response_obj
,
Response
):
# Get the appropriate handler method
response
=
response_obj
if
self
.
method
.
lower
()
in
self
.
http_method_names
:
elif
response_obj
is
not
None
:
handler
=
getattr
(
self
,
self
.
method
.
lower
(),
self
.
http_method_not_allowed
)
response
=
Response
(
status
.
HTTP_200_OK
,
response_obj
)
else
:
else
:
handler
=
self
.
http_method_not_allowed
response
=
Response
(
status
.
HTTP_204_NO_CONTENT
)
response_obj
=
handler
(
request
,
*
args
,
**
kwargs
)
# Pre-serialize filtering (eg filter complex objects into natively serializable types)
response
.
cleaned_content
=
self
.
resource
.
object_to_serializable
(
response
.
raw_content
)
except
ErrorResponse
,
exc
:
# Allow return value to be either Response, or an object, or None
response
=
exc
.
response
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
.
resource
.
object_to_serializable
(
response
.
raw_content
)
except
ErrorResponse
,
exc
:
response
=
exc
.
response
except
:
import
traceback
traceback
.
print_exc
()
# 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
:
except
:
import
traceback
import
traceback
traceback
.
print_exc
()
traceback
.
print_exc
()
# 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