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
1bdc5eac
Commit
1bdc5eac
authored
Dec 29, 2011
by
Tom Christie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add JSONP. Fixes #82
parent
500b0dcd
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
95 additions
and
34 deletions
+95
-34
djangorestframework/renderers.py
+24
-0
djangorestframework/tests/renderers.py
+71
-34
No files found.
djangorestframework/renderers.py
View file @
1bdc5eac
...
@@ -26,6 +26,7 @@ __all__ = (
...
@@ -26,6 +26,7 @@ __all__ = (
'BaseRenderer'
,
'BaseRenderer'
,
'TemplateRenderer'
,
'TemplateRenderer'
,
'JSONRenderer'
,
'JSONRenderer'
,
'JSONPRenderer'
,
'DocumentingHTMLRenderer'
,
'DocumentingHTMLRenderer'
,
'DocumentingXHTMLRenderer'
,
'DocumentingXHTMLRenderer'
,
'DocumentingPlainTextRenderer'
,
'DocumentingPlainTextRenderer'
,
...
@@ -113,6 +114,28 @@ class JSONRenderer(BaseRenderer):
...
@@ -113,6 +114,28 @@ class JSONRenderer(BaseRenderer):
return
json
.
dumps
(
obj
,
cls
=
DateTimeAwareJSONEncoder
,
indent
=
indent
,
sort_keys
=
sort_keys
)
return
json
.
dumps
(
obj
,
cls
=
DateTimeAwareJSONEncoder
,
indent
=
indent
,
sort_keys
=
sort_keys
)
class
JSONPRenderer
(
JSONRenderer
):
"""
Renderer which serializes to JSONP
"""
media_type
=
'application/json-p'
format
=
'json-p'
renderer_class
=
JSONRenderer
callback_parameter
=
'callback'
def
_get_callback
(
self
):
return
self
.
view
.
request
.
GET
.
get
(
self
.
callback_parameter
,
self
.
callback_parameter
)
def
_get_renderer
(
self
):
return
self
.
renderer_class
(
self
.
view
)
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
callback
=
self
.
_get_callback
()
json
=
self
.
_get_renderer
()
.
render
(
obj
,
media_type
)
return
"
%
s(
%
s);"
%
(
callback
,
json
)
class
XMLRenderer
(
BaseRenderer
):
class
XMLRenderer
(
BaseRenderer
):
"""
"""
Renderer which serializes to XML.
Renderer which serializes to XML.
...
@@ -376,6 +399,7 @@ class DocumentingPlainTextRenderer(DocumentingTemplateRenderer):
...
@@ -376,6 +399,7 @@ class DocumentingPlainTextRenderer(DocumentingTemplateRenderer):
DEFAULT_RENDERERS
=
(
JSONRenderer
,
DEFAULT_RENDERERS
=
(
JSONRenderer
,
JSONPRenderer
,
DocumentingHTMLRenderer
,
DocumentingHTMLRenderer
,
DocumentingXHTMLRenderer
,
DocumentingXHTMLRenderer
,
DocumentingPlainTextRenderer
,
DocumentingPlainTextRenderer
,
...
...
djangorestframework/tests/renderers.py
View file @
1bdc5eac
from
django.conf.urls.defaults
import
patterns
,
url
from
django.conf.urls.defaults
import
patterns
,
url
from
django
import
http
from
django.test
import
TestCase
from
django.test
import
TestCase
from
djangorestframework
import
status
from
djangorestframework
import
status
from
djangorestframework.views
import
View
from
djangorestframework.compat
import
View
as
DjangoView
from
djangorestframework.compat
import
View
as
DjangoView
from
djangorestframework.renderers
import
BaseRenderer
,
JSONRenderer
,
YAMLRenderer
,
\
from
djangorestframework.renderers
import
BaseRenderer
,
JSONRenderer
,
YAMLRenderer
,
\
XMLRenderer
XMLRenderer
,
JSONPRenderer
from
djangorestframework.parsers
import
JSONParser
,
YAMLParser
from
djangorestframework.parsers
import
JSONParser
,
YAMLParser
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
from
StringIO
import
StringIO
from
StringIO
import
StringIO
import
datetime
import
datetime
...
@@ -21,31 +20,41 @@ DUMMYCONTENT = 'dummycontent'
...
@@ -21,31 +20,41 @@ DUMMYCONTENT = 'dummycontent'
RENDERER_A_SERIALIZER
=
lambda
x
:
'Renderer A:
%
s'
%
x
RENDERER_A_SERIALIZER
=
lambda
x
:
'Renderer A:
%
s'
%
x
RENDERER_B_SERIALIZER
=
lambda
x
:
'Renderer B:
%
s'
%
x
RENDERER_B_SERIALIZER
=
lambda
x
:
'Renderer B:
%
s'
%
x
class
RendererA
(
BaseRenderer
):
class
RendererA
(
BaseRenderer
):
media_type
=
'mock/renderera'
media_type
=
'mock/renderera'
format
=
"formata"
format
=
"formata"
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
return
RENDERER_A_SERIALIZER
(
obj
)
return
RENDERER_A_SERIALIZER
(
obj
)
class
RendererB
(
BaseRenderer
):
class
RendererB
(
BaseRenderer
):
media_type
=
'mock/rendererb'
media_type
=
'mock/rendererb'
format
=
"formatb"
format
=
"formatb"
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
def
render
(
self
,
obj
=
None
,
media_type
=
None
):
return
RENDERER_B_SERIALIZER
(
obj
)
return
RENDERER_B_SERIALIZER
(
obj
)
class
MockView
(
ResponseMixin
,
DjangoView
):
class
MockView
(
ResponseMixin
,
DjangoView
):
renderers
=
(
RendererA
,
RendererB
)
renderers
=
(
RendererA
,
RendererB
)
def
get
(
self
,
request
,
**
kwargs
):
def
get
(
self
,
request
,
**
kwargs
):
response
=
Response
(
DUMMYSTATUS
,
DUMMYCONTENT
)
response
=
Response
(
DUMMYSTATUS
,
DUMMYCONTENT
)
return
self
.
render
(
response
)
return
self
.
render
(
response
)
class
MockGETView
(
View
):
def
get
(
self
,
request
,
**
kwargs
):
return
{
'foo'
:
[
'bar'
,
'baz'
]}
urlpatterns
=
patterns
(
''
,
urlpatterns
=
patterns
(
''
,
url
(
r'^.*\.(?P<format>.+)$'
,
MockView
.
as_view
(
renderers
=
[
RendererA
,
RendererB
])),
url
(
r'^.*\.(?P<format>.+)$'
,
MockView
.
as_view
(
renderers
=
[
RendererA
,
RendererB
])),
url
(
r'^$'
,
MockView
.
as_view
(
renderers
=
[
RendererA
,
RendererB
])),
url
(
r'^$'
,
MockView
.
as_view
(
renderers
=
[
RendererA
,
RendererB
])),
url
(
r'^jsonp/jsonrenderer$'
,
MockGETView
.
as_view
(
renderers
=
[
JSONRenderer
,
JSONPRenderer
])),
url
(
r'^jsonp/nojsonrenderer$'
,
MockGETView
.
as_view
(
renderers
=
[
JSONPRenderer
])),
)
)
...
@@ -92,7 +101,7 @@ class RendererIntegrationTests(TestCase):
...
@@ -92,7 +101,7 @@ class RendererIntegrationTests(TestCase):
self
.
assertEquals
(
resp
[
'Content-Type'
],
RendererB
.
media_type
)
self
.
assertEquals
(
resp
[
'Content-Type'
],
RendererB
.
media_type
)
self
.
assertEquals
(
resp
.
content
,
RENDERER_B_SERIALIZER
(
DUMMYCONTENT
))
self
.
assertEquals
(
resp
.
content
,
RENDERER_B_SERIALIZER
(
DUMMYCONTENT
))
self
.
assertEquals
(
resp
.
status_code
,
DUMMYSTATUS
)
self
.
assertEquals
(
resp
.
status_code
,
DUMMYSTATUS
)
def
test_specified_renderer_serializes_content_on_accept_query
(
self
):
def
test_specified_renderer_serializes_content_on_accept_query
(
self
):
"""The '_accept' query string should behave in the same way as the Accept header."""
"""The '_accept' query string should behave in the same way as the Accept header."""
resp
=
self
.
client
.
get
(
'/?_accept=
%
s'
%
RendererB
.
media_type
)
resp
=
self
.
client
.
get
(
'/?_accept=
%
s'
%
RendererB
.
media_type
)
...
@@ -147,13 +156,7 @@ class RendererIntegrationTests(TestCase):
...
@@ -147,13 +156,7 @@ class RendererIntegrationTests(TestCase):
self
.
assertEquals
(
resp
.
status_code
,
DUMMYSTATUS
)
self
.
assertEquals
(
resp
.
status_code
,
DUMMYSTATUS
)
_flat_repr
=
'{"foo": ["bar", "baz"]}'
_flat_repr
=
'{"foo": ["bar", "baz"]}'
_indented_repr
=
'{
\n
"foo": [
\n
"bar",
\n
"baz"
\n
]
\n
}'
_indented_repr
=
"""{
"foo": [
"bar",
"baz"
]
}"""
class
JSONRendererTests
(
TestCase
):
class
JSONRendererTests
(
TestCase
):
...
@@ -165,71 +168,106 @@ class JSONRendererTests(TestCase):
...
@@ -165,71 +168,106 @@ class JSONRendererTests(TestCase):
"""
"""
Test basic JSON rendering.
Test basic JSON rendering.
"""
"""
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
renderer
=
JSONRenderer
(
None
)
renderer
=
JSONRenderer
(
None
)
content
=
renderer
.
render
(
obj
,
'application/json'
)
content
=
renderer
.
render
(
obj
,
'application/json'
)
self
.
assertEquals
(
content
,
_flat_repr
)
self
.
assertEquals
(
content
,
_flat_repr
)
def
test_with_content_type_args
(
self
):
def
test_with_content_type_args
(
self
):
"""
"""
Test JSON rendering with additional content type arguments supplied.
Test JSON rendering with additional content type arguments supplied.
"""
"""
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
renderer
=
JSONRenderer
(
None
)
renderer
=
JSONRenderer
(
None
)
content
=
renderer
.
render
(
obj
,
'application/json; indent=2'
)
content
=
renderer
.
render
(
obj
,
'application/json; indent=2'
)
self
.
assertEquals
(
content
,
_indented_repr
)
self
.
assertEquals
(
content
,
_indented_repr
)
def
test_render_and_parse
(
self
):
def
test_render_and_parse
(
self
):
"""
"""
Test rendering and then parsing returns the original object.
Test rendering and then parsing returns the original object.
IE obj -> render -> parse -> obj.
IE obj -> render -> parse -> obj.
"""
"""
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
renderer
=
JSONRenderer
(
None
)
renderer
=
JSONRenderer
(
None
)
parser
=
JSONParser
(
None
)
parser
=
JSONParser
(
None
)
content
=
renderer
.
render
(
obj
,
'application/json'
)
content
=
renderer
.
render
(
obj
,
'application/json'
)
(
data
,
files
)
=
parser
.
parse
(
StringIO
(
content
))
(
data
,
files
)
=
parser
.
parse
(
StringIO
(
content
))
self
.
assertEquals
(
obj
,
data
)
self
.
assertEquals
(
obj
,
data
)
class
JSONPRendererTests
(
TestCase
):
"""
Tests specific to the JSONP Renderer
"""
urls
=
'djangorestframework.tests.renderers'
def
test_without_callback_with_json_renderer
(
self
):
"""
Test JSONP rendering with View JSON Renderer.
"""
resp
=
self
.
client
.
get
(
'/jsonp/jsonrenderer'
,
HTTP_ACCEPT
=
'application/json-p'
)
self
.
assertEquals
(
resp
.
status_code
,
200
)
self
.
assertEquals
(
resp
[
'Content-Type'
],
'application/json-p'
)
self
.
assertEquals
(
resp
.
content
,
'callback(
%
s);'
%
_flat_repr
)
def
test_without_callback_without_json_renderer
(
self
):
"""
Test JSONP rendering without View JSON Renderer.
"""
resp
=
self
.
client
.
get
(
'/jsonp/nojsonrenderer'
,
HTTP_ACCEPT
=
'application/json-p'
)
self
.
assertEquals
(
resp
.
status_code
,
200
)
self
.
assertEquals
(
resp
[
'Content-Type'
],
'application/json-p'
)
self
.
assertEquals
(
resp
.
content
,
'callback(
%
s);'
%
_flat_repr
)
def
test_with_callback
(
self
):
"""
Test JSONP rendering with callback function name.
"""
callback_func
=
'myjsonpcallback'
resp
=
self
.
client
.
get
(
'/jsonp/nojsonrenderer?callback='
+
callback_func
,
HTTP_ACCEPT
=
'application/json-p'
)
self
.
assertEquals
(
resp
.
status_code
,
200
)
self
.
assertEquals
(
resp
[
'Content-Type'
],
'application/json-p'
)
self
.
assertEquals
(
resp
.
content
,
'
%
s(
%
s);'
%
(
callback_func
,
_flat_repr
))
if
YAMLRenderer
:
if
YAMLRenderer
:
_yaml_repr
=
'foo: [bar, baz]
\n
'
_yaml_repr
=
'foo: [bar, baz]
\n
'
class
YAMLRendererTests
(
TestCase
):
class
YAMLRendererTests
(
TestCase
):
"""
"""
Tests specific to the JSON Renderer
Tests specific to the JSON Renderer
"""
"""
def
test_render
(
self
):
def
test_render
(
self
):
"""
"""
Test basic YAML rendering.
Test basic YAML rendering.
"""
"""
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
renderer
=
YAMLRenderer
(
None
)
renderer
=
YAMLRenderer
(
None
)
content
=
renderer
.
render
(
obj
,
'application/yaml'
)
content
=
renderer
.
render
(
obj
,
'application/yaml'
)
self
.
assertEquals
(
content
,
_yaml_repr
)
self
.
assertEquals
(
content
,
_yaml_repr
)
def
test_render_and_parse
(
self
):
def
test_render_and_parse
(
self
):
"""
"""
Test rendering and then parsing returns the original object.
Test rendering and then parsing returns the original object.
IE obj -> render -> parse -> obj.
IE obj -> render -> parse -> obj.
"""
"""
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
obj
=
{
'foo'
:
[
'bar'
,
'baz'
]}
renderer
=
YAMLRenderer
(
None
)
renderer
=
YAMLRenderer
(
None
)
parser
=
YAMLParser
(
None
)
parser
=
YAMLParser
(
None
)
content
=
renderer
.
render
(
obj
,
'application/yaml'
)
content
=
renderer
.
render
(
obj
,
'application/yaml'
)
(
data
,
files
)
=
parser
.
parse
(
StringIO
(
content
))
(
data
,
files
)
=
parser
.
parse
(
StringIO
(
content
))
self
.
assertEquals
(
obj
,
data
)
self
.
assertEquals
(
obj
,
data
)
class
XMLRendererTestCase
(
TestCase
):
class
XMLRendererTestCase
(
TestCase
):
"""
"""
Tests specific to the XML Renderer
Tests specific to the XML Renderer
...
@@ -285,8 +323,7 @@ class XMLRendererTestCase(TestCase):
...
@@ -285,8 +323,7 @@ class XMLRendererTestCase(TestCase):
content
=
renderer
.
render
({
'field'
:
None
},
'application/xml'
)
content
=
renderer
.
render
({
'field'
:
None
},
'application/xml'
)
self
.
assertXMLContains
(
content
,
'<field></field>'
)
self
.
assertXMLContains
(
content
,
'<field></field>'
)
def
assertXMLContains
(
self
,
xml
,
string
):
def
assertXMLContains
(
self
,
xml
,
string
):
self
.
assertTrue
(
xml
.
startswith
(
'<?xml version="1.0" encoding="utf-8"?>
\n
<root>'
))
self
.
assertTrue
(
xml
.
startswith
(
'<?xml version="1.0" encoding="utf-8"?>
\n
<root>'
))
self
.
assertTrue
(
xml
.
endswith
(
'</root>'
))
self
.
assertTrue
(
xml
.
endswith
(
'</root>'
))
self
.
assertTrue
(
string
in
xml
,
'
%
r not in
%
r'
%
(
string
,
xml
))
self
.
assertTrue
(
string
in
xml
,
'
%
r not in
%
r'
%
(
string
,
xml
))
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