JSONP renderer and tests

This commit is contained in:
garciasolero 2011-10-14 09:29:55 +02:00
parent 2caf879f22
commit 9516b26a80
2 changed files with 90 additions and 2 deletions

View File

@ -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,

View File

@ -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: