mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-18 04:02:35 +03:00
JSONP renderer and tests
This commit is contained in:
parent
2caf879f22
commit
9516b26a80
|
@ -26,6 +26,7 @@ __all__ = (
|
|||
'BaseRenderer',
|
||||
'TemplateRenderer',
|
||||
'JSONRenderer',
|
||||
'JSONPRenderer',
|
||||
'DocumentingHTMLRenderer',
|
||||
'DocumentingXHTMLRenderer',
|
||||
'DocumentingPlainTextRenderer',
|
||||
|
@ -113,6 +114,46 @@ class JSONRenderer(BaseRenderer):
|
|||
return json.dumps(obj, cls=DateTimeAwareJSONEncoder, indent=indent, sort_keys=sort_keys)
|
||||
|
||||
|
||||
class JSONPRenderer(BaseRenderer):
|
||||
"""
|
||||
Renderer which serializes to JSONP
|
||||
"""
|
||||
media_type = 'application/json-p'
|
||||
format = 'json-p'
|
||||
|
||||
callback_parameter = 'callback'
|
||||
|
||||
def render(self, obj=None, media_type=None):
|
||||
"""
|
||||
Renders *obj* into serialized JSONP.
|
||||
|
||||
The callback function name is taken from the 'callback' parameter
|
||||
contained in the jsonp request.
|
||||
"""
|
||||
callback = self.view.request.GET.get(self.callback_parameter, self.callback_parameter)
|
||||
|
||||
if obj is None:
|
||||
serialized_obj = ''
|
||||
else:
|
||||
json_renderer = self._get_renderer(JSONRenderer.media_type)
|
||||
if json_renderer is None:
|
||||
serialized_obj = json.dumps(obj, cls=DateTimeAwareJSONEncoder)
|
||||
else:
|
||||
serialized_obj = json_renderer.render(obj, JSONRenderer.media_type)
|
||||
|
||||
return "%s(%s);" % (callback, serialized_obj)
|
||||
|
||||
def _get_renderer(self, media_type=None):
|
||||
"""
|
||||
Get first view renderer that serializes *media_type*.
|
||||
"""
|
||||
for r in self.view.renderers:
|
||||
renderer = r(self.view)
|
||||
if renderer.can_handle_response(media_type):
|
||||
return renderer
|
||||
return None
|
||||
|
||||
|
||||
class XMLRenderer(BaseRenderer):
|
||||
"""
|
||||
Renderer which serializes to XML.
|
||||
|
@ -376,6 +417,7 @@ class DocumentingPlainTextRenderer(DocumentingTemplateRenderer):
|
|||
|
||||
|
||||
DEFAULT_RENDERERS = ( JSONRenderer,
|
||||
JSONPRenderer,
|
||||
DocumentingHTMLRenderer,
|
||||
DocumentingXHTMLRenderer,
|
||||
DocumentingPlainTextRenderer,
|
||||
|
|
|
@ -3,8 +3,10 @@ from django import http
|
|||
from django.test import TestCase
|
||||
|
||||
from djangorestframework import status
|
||||
from djangorestframework.views import View
|
||||
from djangorestframework.compat import View as DjangoView
|
||||
from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer
|
||||
from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
|
||||
JSONPRenderer
|
||||
from djangorestframework.parsers import JSONParser, YAMLParser
|
||||
from djangorestframework.mixins import ResponseMixin
|
||||
from djangorestframework.response import Response
|
||||
|
@ -39,10 +41,16 @@ class MockView(ResponseMixin, DjangoView):
|
|||
response = Response(DUMMYSTATUS, DUMMYCONTENT)
|
||||
return self.render(response)
|
||||
|
||||
class MockGETView(View):
|
||||
def get(self, request, **kwargs):
|
||||
return {'foo':['bar','baz']}
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^.*\.(?P<format>.+)$', 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])),
|
||||
)
|
||||
|
||||
|
||||
|
@ -188,8 +196,46 @@ class JSONRendererTests(TestCase):
|
|||
|
||||
content = renderer.render(obj, 'application/json')
|
||||
(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:
|
||||
|
|
Loading…
Reference in New Issue
Block a user