mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 13:14:30 +03:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
1b28339e5b
1
AUTHORS
1
AUTHORS
|
@ -20,6 +20,7 @@ Andrew McCloud <amccloud>
|
|||
Thomas Steinacher <thomasst>
|
||||
Meurig Freeman <meurig>
|
||||
Anthony Nemitz <anemitz>
|
||||
Ewoud Kohl van Wijngaarden <ekohl>
|
||||
|
||||
THANKS TO:
|
||||
|
||||
|
|
5
RELEASES
5
RELEASES
|
@ -1,3 +1,8 @@
|
|||
0.3.0
|
||||
|
||||
* JSONP Support
|
||||
* Bugfixes, including support for latest markdown release
|
||||
|
||||
0.2.4
|
||||
|
||||
* Fix broken IsAdminUser permission.
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
__version__ = '0.2.4'
|
||||
__version__ = '0.3.1-dev'
|
||||
|
||||
VERSION = __version__ # synonym
|
||||
|
|
|
@ -26,6 +26,7 @@ __all__ = (
|
|||
'BaseRenderer',
|
||||
'TemplateRenderer',
|
||||
'JSONRenderer',
|
||||
'JSONPRenderer',
|
||||
'DocumentingHTMLRenderer',
|
||||
'DocumentingXHTMLRenderer',
|
||||
'DocumentingPlainTextRenderer',
|
||||
|
@ -113,6 +114,28 @@ class JSONRenderer(BaseRenderer):
|
|||
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):
|
||||
"""
|
||||
Renderer which serializes to XML.
|
||||
|
@ -376,6 +399,7 @@ class DocumentingPlainTextRenderer(DocumentingTemplateRenderer):
|
|||
|
||||
|
||||
DEFAULT_RENDERERS = ( JSONRenderer,
|
||||
JSONPRenderer,
|
||||
DocumentingHTMLRenderer,
|
||||
DocumentingXHTMLRenderer,
|
||||
DocumentingPlainTextRenderer,
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
from django.conf.urls.defaults import patterns, url
|
||||
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, \
|
||||
XMLRenderer
|
||||
XMLRenderer, JSONPRenderer
|
||||
from djangorestframework.parsers import JSONParser, YAMLParser
|
||||
from djangorestframework.mixins import ResponseMixin
|
||||
from djangorestframework.response import Response
|
||||
from djangorestframework.utils.mediatypes import add_media_type_param
|
||||
|
||||
from StringIO import StringIO
|
||||
import datetime
|
||||
|
@ -21,6 +20,7 @@ DUMMYCONTENT = 'dummycontent'
|
|||
RENDERER_A_SERIALIZER = lambda x: 'Renderer A: %s' % x
|
||||
RENDERER_B_SERIALIZER = lambda x: 'Renderer B: %s' % x
|
||||
|
||||
|
||||
class RendererA(BaseRenderer):
|
||||
media_type = 'mock/renderera'
|
||||
format = "formata"
|
||||
|
@ -28,6 +28,7 @@ class RendererA(BaseRenderer):
|
|||
def render(self, obj=None, media_type=None):
|
||||
return RENDERER_A_SERIALIZER(obj)
|
||||
|
||||
|
||||
class RendererB(BaseRenderer):
|
||||
media_type = 'mock/rendererb'
|
||||
format = "formatb"
|
||||
|
@ -35,6 +36,7 @@ class RendererB(BaseRenderer):
|
|||
def render(self, obj=None, media_type=None):
|
||||
return RENDERER_B_SERIALIZER(obj)
|
||||
|
||||
|
||||
class MockView(ResponseMixin, DjangoView):
|
||||
renderers = (RendererA, RendererB)
|
||||
|
||||
|
@ -43,9 +45,16 @@ class MockView(ResponseMixin, DjangoView):
|
|||
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])),
|
||||
)
|
||||
|
||||
|
||||
|
@ -147,13 +156,7 @@ class RendererIntegrationTests(TestCase):
|
|||
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
||||
|
||||
_flat_repr = '{"foo": ["bar", "baz"]}'
|
||||
|
||||
_indented_repr = """{
|
||||
"foo": [
|
||||
"bar",
|
||||
"baz"
|
||||
]
|
||||
}"""
|
||||
_indented_repr = '{\n "foo": [\n "bar", \n "baz"\n ]\n}'
|
||||
|
||||
|
||||
class JSONRendererTests(TestCase):
|
||||
|
@ -194,11 +197,48 @@ class JSONRendererTests(TestCase):
|
|||
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:
|
||||
_yaml_repr = 'foo: [bar, baz]\n'
|
||||
|
||||
|
||||
class YAMLRendererTests(TestCase):
|
||||
"""
|
||||
Tests specific to the JSON Renderer
|
||||
|
@ -213,7 +253,6 @@ if YAMLRenderer:
|
|||
content = renderer.render(obj, 'application/yaml')
|
||||
self.assertEquals(content, _yaml_repr)
|
||||
|
||||
|
||||
def test_render_and_parse(self):
|
||||
"""
|
||||
Test rendering and then parsing returns the original object.
|
||||
|
@ -229,7 +268,6 @@ if YAMLRenderer:
|
|||
self.assertEquals(obj, data)
|
||||
|
||||
|
||||
|
||||
class XMLRendererTestCase(TestCase):
|
||||
"""
|
||||
Tests specific to the XML Renderer
|
||||
|
@ -285,7 +323,6 @@ class XMLRendererTestCase(TestCase):
|
|||
content = renderer.render({'field': None}, 'application/xml')
|
||||
self.assertXMLContains(content, '<field></field>')
|
||||
|
||||
|
||||
def assertXMLContains(self, xml, string):
|
||||
self.assertTrue(xml.startswith('<?xml version="1.0" encoding="utf-8"?>\n<root>'))
|
||||
self.assertTrue(xml.endswith('</root>'))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Blog Posts API
|
||||
==============
|
||||
|
||||
* http://api.django-rest-framework.org/blog-post/
|
||||
* http://rest.ep.io/blog-post/
|
||||
|
||||
The models
|
||||
----------
|
||||
|
|
|
@ -5,11 +5,11 @@ Getting Started - Model Views
|
|||
|
||||
A live sandbox instance of this API is available:
|
||||
|
||||
http://api.django-rest-framework.org/model-resource-example/
|
||||
http://rest.ep.io/model-resource-example/
|
||||
|
||||
You can browse the API using a web browser, or from the command line::
|
||||
|
||||
curl -X GET http://api.django-rest-framework.org/resource-example/ -H 'Accept: text/plain'
|
||||
curl -X GET http://rest.ep.io/resource-example/ -H 'Accept: text/plain'
|
||||
|
||||
Often you'll want parts of your API to directly map to existing django models. Django REST framework handles this nicely for you in a couple of ways:
|
||||
|
||||
|
@ -41,16 +41,16 @@ And we're done. We've now got a fully browseable API, which supports multiple i
|
|||
|
||||
We can visit the API in our browser:
|
||||
|
||||
* http://api.django-rest-framework.org/model-resource-example/
|
||||
* http://rest.ep.io/model-resource-example/
|
||||
|
||||
Or access it from the command line using curl:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Demonstrates API's input validation using form input
|
||||
bash: curl -X POST --data 'foo=true' http://api.django-rest-framework.org/model-resource-example/
|
||||
bash: curl -X POST --data 'foo=true' http://rest.ep.io/model-resource-example/
|
||||
{"detail": {"bar": ["This field is required."], "baz": ["This field is required."]}}
|
||||
|
||||
# Demonstrates API's input validation using JSON input
|
||||
bash: curl -X POST -H 'Content-Type: application/json' --data-binary '{"foo":true}' http://api.django-rest-framework.org/model-resource-example/
|
||||
bash: curl -X POST -H 'Content-Type: application/json' --data-binary '{"foo":true}' http://rest.ep.io/model-resource-example/
|
||||
{"detail": {"bar": ["This field is required."], "baz": ["This field is required."]}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Object Store API
|
||||
================
|
||||
|
||||
* http://api.django-rest-framework.org/object-store/
|
||||
* http://rest.ep.io/object-store/
|
||||
|
||||
This example shows an object store API that can be used to store arbitrary serializable content.
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@ We're going to provide a simple wrapper around the awesome `pygments <http://pyg
|
|||
|
||||
.. note::
|
||||
|
||||
A live sandbox instance of this API is available at http://api.django-rest-framework.org/pygments/
|
||||
A live sandbox instance of this API is available at http://rest.ep.io/pygments/
|
||||
|
||||
You can browse the API using a web browser, or from the command line::
|
||||
|
||||
curl -X GET http://api.django-rest-framework.org/pygments/ -H 'Accept: text/plain'
|
||||
curl -X GET http://rest.ep.io/pygments/ -H 'Accept: text/plain'
|
||||
|
||||
|
||||
URL configuration
|
||||
|
@ -77,13 +77,13 @@ For example if we make a POST request using form input:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
bash: curl -X POST --data 'code=print "hello, world!"' --data 'style=foobar' -H 'X-Requested-With: XMLHttpRequest' http://api.django-rest-framework.org/pygments/
|
||||
bash: curl -X POST --data 'code=print "hello, world!"' --data 'style=foobar' -H 'X-Requested-With: XMLHttpRequest' http://rest.ep.io/pygments/
|
||||
{"detail": {"style": ["Select a valid choice. foobar is not one of the available choices."], "lexer": ["This field is required."]}}
|
||||
|
||||
Or if we make the same request using JSON:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
bash: curl -X POST --data-binary '{"code":"print \"hello, world!\"", "style":"foobar"}' -H 'Content-Type: application/json' -H 'X-Requested-With: XMLHttpRequest' http://api.django-rest-framework.org/pygments/
|
||||
bash: curl -X POST --data-binary '{"code":"print \"hello, world!\"", "style":"foobar"}' -H 'Content-Type: application/json' -H 'X-Requested-With: XMLHttpRequest' http://rest.ep.io/pygments/
|
||||
{"detail": {"style": ["Select a valid choice. foobar is not one of the available choices."], "lexer": ["This field is required."]}}
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@ Getting Started - Views
|
|||
|
||||
A live sandbox instance of this API is available:
|
||||
|
||||
http://api.django-rest-framework.org/resource-example/
|
||||
http://rest.ep.io/resource-example/
|
||||
|
||||
You can browse the API using a web browser, or from the command line::
|
||||
|
||||
curl -X GET http://api.django-rest-framework.org/resource-example/ -H 'Accept: text/plain'
|
||||
curl -X GET http://rest.ep.io/resource-example/ -H 'Accept: text/plain'
|
||||
|
||||
We're going to start off with a simple example, that demonstrates a few things:
|
||||
|
||||
|
@ -41,16 +41,16 @@ Now we'll write our views. The first is a read only view that links to three in
|
|||
|
||||
That's us done. Our API now provides both programmatic access using JSON and XML, as well a nice browseable HTML view, so we can now access it both from the browser:
|
||||
|
||||
* http://api.django-rest-framework.org/resource-example/
|
||||
* http://rest.ep.io/resource-example/
|
||||
|
||||
And from the command line:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Demonstrates API's input validation using form input
|
||||
bash: curl -X POST --data 'foo=true' http://api.django-rest-framework.org/resource-example/1/
|
||||
bash: curl -X POST --data 'foo=true' http://rest.ep.io/resource-example/1/
|
||||
{"detail": {"bar": ["This field is required."], "baz": ["This field is required."]}}
|
||||
|
||||
# Demonstrates API's input validation using JSON input
|
||||
bash: curl -X POST -H 'Content-Type: application/json' --data-binary '{"foo":true}' http://api.django-rest-framework.org/resource-example/1/
|
||||
bash: curl -X POST -H 'Content-Type: application/json' --data-binary '{"foo":true}' http://rest.ep.io/resource-example/1/
|
||||
{"detail": {"bar": ["This field is required."], "baz": ["This field is required."]}}
|
||||
|
|
|
@ -9,11 +9,11 @@ a browseable Web API, and much of the other goodness that Django REST framework
|
|||
|
||||
A live sandbox instance of this API is available for testing:
|
||||
|
||||
* http://api.django-rest-framework.org/mixin/
|
||||
* http://rest.ep.io/mixin/
|
||||
|
||||
You can browse the API using a web browser, or from the command line::
|
||||
|
||||
curl -X GET http://api.django-rest-framework.org/mixin/
|
||||
curl -X GET http://rest.ep.io/mixin/
|
||||
|
||||
|
||||
URL configuration
|
||||
|
|
|
@ -11,11 +11,11 @@ Introduction
|
|||
|
||||
Django REST framework is a lightweight REST framework for Django, that aims to make it easy to build well-connected, self-describing RESTful Web APIs.
|
||||
|
||||
**Browse example APIs created with Django REST framework:** `The Sandbox <http://api.django-rest-framework.org/>`_
|
||||
**Browse example APIs created with Django REST framework:** `The Sandbox <http://rest.ep.io/>`_
|
||||
|
||||
Features:
|
||||
|
||||
* Automatically provides an awesome Django admin style `browse-able self-documenting API <http://api.django-rest-framework.org>`_.
|
||||
* Automatically provides an awesome Django admin style `browse-able self-documenting API <http://rest.ep.io>`_.
|
||||
* Clean, simple, views for Resources, using Django's new `class based views <http://docs.djangoproject.com/en/dev/topics/class-based-views/>`_.
|
||||
* Support for ModelResources with out-of-the-box default implementations and input validation.
|
||||
* Pluggable :mod:`.parsers`, :mod:`renderers`, :mod:`authentication` and :mod:`permissions` - Easy to customise.
|
||||
|
@ -101,7 +101,7 @@ There are a few real world web API examples included with Django REST framework.
|
|||
|
||||
All the examples are freely available for testing in the sandbox:
|
||||
|
||||
http://api.django-rest-framework.org
|
||||
http://rest.ep.io
|
||||
|
||||
(The :doc:`examples/sandbox` resource is also documented.)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user