mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-11 04:07:39 +03:00
Merge branch 'jpadilla-jsonp' into version-3.1
This commit is contained in:
commit
cd4d866021
|
@ -49,10 +49,10 @@ using the `APIView` class based views.
|
|||
Or, if you're using the `@api_view` decorator with function based views.
|
||||
|
||||
@api_view(['GET'])
|
||||
@renderer_classes((JSONRenderer, JSONPRenderer))
|
||||
@renderer_classes((JSONRenderer,))
|
||||
def user_count_view(request, format=None):
|
||||
"""
|
||||
A view that returns the count of active users, in JSON or JSONp.
|
||||
A view that returns the count of active users in JSON.
|
||||
"""
|
||||
user_count = User.objects.filter(active=True).count()
|
||||
content = {'user_count': user_count}
|
||||
|
@ -93,26 +93,6 @@ The default JSON encoding style can be altered using the `UNICODE_JSON` and `COM
|
|||
|
||||
**.charset**: `None`
|
||||
|
||||
## JSONPRenderer
|
||||
|
||||
Renders the request data into `JSONP`. The `JSONP` media type provides a mechanism of allowing cross-domain AJAX requests, by wrapping a `JSON` response in a javascript callback.
|
||||
|
||||
The javascript callback function must be set by the client including a `callback` URL query parameter. For example `http://example.com/api/users?callback=jsonpCallback`. If the callback function is not explicitly set by the client it will default to `'callback'`.
|
||||
|
||||
---
|
||||
|
||||
**Warning**: If you require cross-domain AJAX requests, you should almost certainly be using the more modern approach of [CORS][cors] as an alternative to `JSONP`. See the [CORS documentation][cors-docs] for more details.
|
||||
|
||||
The `jsonp` approach is essentially a browser hack, and is [only appropriate for globally readable API endpoints][jsonp-security], where `GET` requests are unauthenticated and do not require any user permissions.
|
||||
|
||||
---
|
||||
|
||||
**.media_type**: `application/javascript`
|
||||
|
||||
**.format**: `'.jsonp'`
|
||||
|
||||
**.charset**: `utf-8`
|
||||
|
||||
## YAMLRenderer
|
||||
|
||||
Renders the request data into `YAML`.
|
||||
|
@ -419,10 +399,6 @@ Comma-separated values are a plain-text tabular data format, that can be easily
|
|||
[cite]: https://docs.djangoproject.com/en/dev/ref/template-response/#the-rendering-process
|
||||
[conneg]: content-negotiation.md
|
||||
[browser-accept-headers]: http://www.gethifi.com/blog/browser-rest-http-accept-headers
|
||||
[rfc4627]: http://www.ietf.org/rfc/rfc4627.txt
|
||||
[cors]: http://www.w3.org/TR/cors/
|
||||
[cors-docs]: ../topics/ajax-csrf-cors.md
|
||||
[jsonp-security]: http://stackoverflow.com/questions/613962/is-jsonp-safe-to-use
|
||||
[testing]: testing.md
|
||||
[HATEOAS]: http://timelessrepo.com/haters-gonna-hateoas
|
||||
[quote]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
|
||||
|
|
|
@ -103,40 +103,6 @@ class JSONRenderer(BaseRenderer):
|
|||
return ret
|
||||
|
||||
|
||||
class JSONPRenderer(JSONRenderer):
|
||||
"""
|
||||
Renderer which serializes to json,
|
||||
wrapping the json output in a callback function.
|
||||
"""
|
||||
|
||||
media_type = 'application/javascript'
|
||||
format = 'jsonp'
|
||||
callback_parameter = 'callback'
|
||||
default_callback = 'callback'
|
||||
charset = 'utf-8'
|
||||
|
||||
def get_callback(self, renderer_context):
|
||||
"""
|
||||
Determine the name of the callback to wrap around the json output.
|
||||
"""
|
||||
request = renderer_context.get('request', None)
|
||||
params = request and request.query_params or {}
|
||||
return params.get(self.callback_parameter, self.default_callback)
|
||||
|
||||
def render(self, data, accepted_media_type=None, renderer_context=None):
|
||||
"""
|
||||
Renders into jsonp, wrapping the json output in a callback function.
|
||||
|
||||
Clients may set the callback function name using a query parameter
|
||||
on the URL, for example: ?callback=exampleCallbackName
|
||||
"""
|
||||
renderer_context = renderer_context or {}
|
||||
callback = self.get_callback(renderer_context)
|
||||
json = super(JSONPRenderer, self).render(data, accepted_media_type,
|
||||
renderer_context)
|
||||
return callback.encode(self.charset) + b'(' + json + b');'
|
||||
|
||||
|
||||
class YAMLRenderer(BaseRenderer):
|
||||
"""
|
||||
Renderer which serializes to YAML.
|
||||
|
|
|
@ -12,8 +12,7 @@ from rest_framework import status, permissions
|
|||
from rest_framework.compat import yaml, BytesIO
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
|
||||
JSONPRenderer, BrowsableAPIRenderer
|
||||
from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, BrowsableAPIRenderer
|
||||
from rest_framework.parsers import YAMLParser
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.test import APIRequestFactory
|
||||
|
@ -105,8 +104,6 @@ urlpatterns = patterns(
|
|||
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
|
||||
url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
|
||||
url(r'^cache$', MockGETView.as_view()),
|
||||
url(r'^jsonp/jsonrenderer$', MockGETView.as_view(renderer_classes=[JSONRenderer, JSONPRenderer])),
|
||||
url(r'^jsonp/nojsonrenderer$', MockGETView.as_view(renderer_classes=[JSONPRenderer])),
|
||||
url(r'^parseerror$', MockPOSTView.as_view(renderer_classes=[JSONRenderer, BrowsableAPIRenderer])),
|
||||
url(r'^html$', HTMLView.as_view()),
|
||||
url(r'^html1$', HTMLView1.as_view()),
|
||||
|
@ -397,60 +394,6 @@ class AsciiJSONRendererTests(TestCase):
|
|||
self.assertEqual(content, '{"countries":["United Kingdom","France","Espa\\u00f1a"]}'.encode('utf-8'))
|
||||
|
||||
|
||||
class JSONPRendererTests(TestCase):
|
||||
"""
|
||||
Tests specific to the JSONP Renderer
|
||||
"""
|
||||
|
||||
urls = 'tests.test_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/javascript'
|
||||
)
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(resp['Content-Type'], 'application/javascript; charset=utf-8')
|
||||
self.assertEqual(
|
||||
resp.content,
|
||||
('callback(%s);' % _flat_repr).encode('ascii')
|
||||
)
|
||||
|
||||
def test_without_callback_without_json_renderer(self):
|
||||
"""
|
||||
Test JSONP rendering without View JSON Renderer.
|
||||
"""
|
||||
resp = self.client.get(
|
||||
'/jsonp/nojsonrenderer',
|
||||
HTTP_ACCEPT='application/javascript'
|
||||
)
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(resp['Content-Type'], 'application/javascript; charset=utf-8')
|
||||
self.assertEqual(
|
||||
resp.content,
|
||||
('callback(%s);' % _flat_repr).encode('ascii')
|
||||
)
|
||||
|
||||
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/javascript'
|
||||
)
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(resp['Content-Type'], 'application/javascript; charset=utf-8')
|
||||
self.assertEqual(
|
||||
resp.content,
|
||||
('%s(%s);' % (callback_func, _flat_repr)).encode('ascii')
|
||||
)
|
||||
|
||||
|
||||
if yaml:
|
||||
_yaml_repr = 'foo: [bar, baz]\n'
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user