Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Marko Tibold 2011-12-30 01:37:32 +01:00
commit 1b28339e5b
62 changed files with 474 additions and 407 deletions

View File

@ -20,6 +20,7 @@ Andrew McCloud <amccloud>
Thomas Steinacher <thomasst>
Meurig Freeman <meurig>
Anthony Nemitz <anemitz>
Ewoud Kohl van Wijngaarden <ekohl>
THANKS TO:

View File

@ -1,3 +1,8 @@
0.3.0
* JSONP Support
* Bugfixes, including support for latest markdown release
0.2.4
* Fix broken IsAdminUser permission.

View File

@ -1,3 +1,3 @@
__version__ = '0.2.4'
__version__ = '0.3.1-dev'
VERSION = __version__ # synonym

View File

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

View File

@ -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>'))

View File

@ -1,7 +1,7 @@
Blog Posts API
==============
* http://api.django-rest-framework.org/blog-post/
* http://rest.ep.io/blog-post/
The models
----------

View File

@ -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."]}}

View File

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

View File

@ -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."]}}

View File

@ -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."]}}

View File

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

View File

@ -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.)