mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-03 20:03:35 +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>
|
Thomas Steinacher <thomasst>
|
||||||
Meurig Freeman <meurig>
|
Meurig Freeman <meurig>
|
||||||
Anthony Nemitz <anemitz>
|
Anthony Nemitz <anemitz>
|
||||||
|
Ewoud Kohl van Wijngaarden <ekohl>
|
||||||
|
|
||||||
THANKS TO:
|
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
|
0.2.4
|
||||||
|
|
||||||
* Fix broken IsAdminUser permission.
|
* Fix broken IsAdminUser permission.
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
__version__ = '0.2.4'
|
__version__ = '0.3.1-dev'
|
||||||
|
|
||||||
VERSION = __version__ # synonym
|
VERSION = __version__ # synonym
|
||||||
|
|
|
@ -26,6 +26,7 @@ __all__ = (
|
||||||
'BaseRenderer',
|
'BaseRenderer',
|
||||||
'TemplateRenderer',
|
'TemplateRenderer',
|
||||||
'JSONRenderer',
|
'JSONRenderer',
|
||||||
|
'JSONPRenderer',
|
||||||
'DocumentingHTMLRenderer',
|
'DocumentingHTMLRenderer',
|
||||||
'DocumentingXHTMLRenderer',
|
'DocumentingXHTMLRenderer',
|
||||||
'DocumentingPlainTextRenderer',
|
'DocumentingPlainTextRenderer',
|
||||||
|
@ -113,6 +114,28 @@ class JSONRenderer(BaseRenderer):
|
||||||
return json.dumps(obj, cls=DateTimeAwareJSONEncoder, indent=indent, sort_keys=sort_keys)
|
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):
|
class XMLRenderer(BaseRenderer):
|
||||||
"""
|
"""
|
||||||
Renderer which serializes to XML.
|
Renderer which serializes to XML.
|
||||||
|
@ -376,6 +399,7 @@ class DocumentingPlainTextRenderer(DocumentingTemplateRenderer):
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_RENDERERS = ( JSONRenderer,
|
DEFAULT_RENDERERS = ( JSONRenderer,
|
||||||
|
JSONPRenderer,
|
||||||
DocumentingHTMLRenderer,
|
DocumentingHTMLRenderer,
|
||||||
DocumentingXHTMLRenderer,
|
DocumentingXHTMLRenderer,
|
||||||
DocumentingPlainTextRenderer,
|
DocumentingPlainTextRenderer,
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
from django.conf.urls.defaults import patterns, url
|
from django.conf.urls.defaults import patterns, url
|
||||||
from django import http
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from djangorestframework import status
|
from djangorestframework import status
|
||||||
|
from djangorestframework.views import View
|
||||||
from djangorestframework.compat import View as DjangoView
|
from djangorestframework.compat import View as DjangoView
|
||||||
from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
|
from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
|
||||||
XMLRenderer
|
XMLRenderer, JSONPRenderer
|
||||||
from djangorestframework.parsers import JSONParser, YAMLParser
|
from djangorestframework.parsers import JSONParser, YAMLParser
|
||||||
from djangorestframework.mixins import ResponseMixin
|
from djangorestframework.mixins import ResponseMixin
|
||||||
from djangorestframework.response import Response
|
from djangorestframework.response import Response
|
||||||
from djangorestframework.utils.mediatypes import add_media_type_param
|
|
||||||
|
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -21,6 +20,7 @@ DUMMYCONTENT = 'dummycontent'
|
||||||
RENDERER_A_SERIALIZER = lambda x: 'Renderer A: %s' % x
|
RENDERER_A_SERIALIZER = lambda x: 'Renderer A: %s' % x
|
||||||
RENDERER_B_SERIALIZER = lambda x: 'Renderer B: %s' % x
|
RENDERER_B_SERIALIZER = lambda x: 'Renderer B: %s' % x
|
||||||
|
|
||||||
|
|
||||||
class RendererA(BaseRenderer):
|
class RendererA(BaseRenderer):
|
||||||
media_type = 'mock/renderera'
|
media_type = 'mock/renderera'
|
||||||
format = "formata"
|
format = "formata"
|
||||||
|
@ -28,6 +28,7 @@ class RendererA(BaseRenderer):
|
||||||
def render(self, obj=None, media_type=None):
|
def render(self, obj=None, media_type=None):
|
||||||
return RENDERER_A_SERIALIZER(obj)
|
return RENDERER_A_SERIALIZER(obj)
|
||||||
|
|
||||||
|
|
||||||
class RendererB(BaseRenderer):
|
class RendererB(BaseRenderer):
|
||||||
media_type = 'mock/rendererb'
|
media_type = 'mock/rendererb'
|
||||||
format = "formatb"
|
format = "formatb"
|
||||||
|
@ -35,6 +36,7 @@ class RendererB(BaseRenderer):
|
||||||
def render(self, obj=None, media_type=None):
|
def render(self, obj=None, media_type=None):
|
||||||
return RENDERER_B_SERIALIZER(obj)
|
return RENDERER_B_SERIALIZER(obj)
|
||||||
|
|
||||||
|
|
||||||
class MockView(ResponseMixin, DjangoView):
|
class MockView(ResponseMixin, DjangoView):
|
||||||
renderers = (RendererA, RendererB)
|
renderers = (RendererA, RendererB)
|
||||||
|
|
||||||
|
@ -43,9 +45,16 @@ class MockView(ResponseMixin, DjangoView):
|
||||||
return self.render(response)
|
return self.render(response)
|
||||||
|
|
||||||
|
|
||||||
|
class MockGETView(View):
|
||||||
|
def get(self, request, **kwargs):
|
||||||
|
return {'foo': ['bar', 'baz']}
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderers=[RendererA, RendererB])),
|
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderers=[RendererA, RendererB])),
|
||||||
url(r'^$', 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)
|
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
||||||
|
|
||||||
_flat_repr = '{"foo": ["bar", "baz"]}'
|
_flat_repr = '{"foo": ["bar", "baz"]}'
|
||||||
|
_indented_repr = '{\n "foo": [\n "bar", \n "baz"\n ]\n}'
|
||||||
_indented_repr = """{
|
|
||||||
"foo": [
|
|
||||||
"bar",
|
|
||||||
"baz"
|
|
||||||
]
|
|
||||||
}"""
|
|
||||||
|
|
||||||
|
|
||||||
class JSONRendererTests(TestCase):
|
class JSONRendererTests(TestCase):
|
||||||
|
@ -194,11 +197,48 @@ class JSONRendererTests(TestCase):
|
||||||
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:
|
if YAMLRenderer:
|
||||||
_yaml_repr = 'foo: [bar, baz]\n'
|
_yaml_repr = 'foo: [bar, baz]\n'
|
||||||
|
|
||||||
|
|
||||||
class YAMLRendererTests(TestCase):
|
class YAMLRendererTests(TestCase):
|
||||||
"""
|
"""
|
||||||
Tests specific to the JSON Renderer
|
Tests specific to the JSON Renderer
|
||||||
|
@ -213,7 +253,6 @@ if YAMLRenderer:
|
||||||
content = renderer.render(obj, 'application/yaml')
|
content = renderer.render(obj, 'application/yaml')
|
||||||
self.assertEquals(content, _yaml_repr)
|
self.assertEquals(content, _yaml_repr)
|
||||||
|
|
||||||
|
|
||||||
def test_render_and_parse(self):
|
def test_render_and_parse(self):
|
||||||
"""
|
"""
|
||||||
Test rendering and then parsing returns the original object.
|
Test rendering and then parsing returns the original object.
|
||||||
|
@ -229,7 +268,6 @@ if YAMLRenderer:
|
||||||
self.assertEquals(obj, data)
|
self.assertEquals(obj, data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class XMLRendererTestCase(TestCase):
|
class XMLRendererTestCase(TestCase):
|
||||||
"""
|
"""
|
||||||
Tests specific to the XML Renderer
|
Tests specific to the XML Renderer
|
||||||
|
@ -285,7 +323,6 @@ class XMLRendererTestCase(TestCase):
|
||||||
content = renderer.render({'field': None}, 'application/xml')
|
content = renderer.render({'field': None}, 'application/xml')
|
||||||
self.assertXMLContains(content, '<field></field>')
|
self.assertXMLContains(content, '<field></field>')
|
||||||
|
|
||||||
|
|
||||||
def assertXMLContains(self, xml, string):
|
def assertXMLContains(self, xml, string):
|
||||||
self.assertTrue(xml.startswith('<?xml version="1.0" encoding="utf-8"?>\n<root>'))
|
self.assertTrue(xml.startswith('<?xml version="1.0" encoding="utf-8"?>\n<root>'))
|
||||||
self.assertTrue(xml.endswith('</root>'))
|
self.assertTrue(xml.endswith('</root>'))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Blog Posts API
|
Blog Posts API
|
||||||
==============
|
==============
|
||||||
|
|
||||||
* http://api.django-rest-framework.org/blog-post/
|
* http://rest.ep.io/blog-post/
|
||||||
|
|
||||||
The models
|
The models
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -5,11 +5,11 @@ Getting Started - Model Views
|
||||||
|
|
||||||
A live sandbox instance of this API is available:
|
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::
|
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:
|
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:
|
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:
|
Or access it from the command line using curl:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# Demonstrates API's input validation using form input
|
# 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."]}}
|
{"detail": {"bar": ["This field is required."], "baz": ["This field is required."]}}
|
||||||
|
|
||||||
# Demonstrates API's input validation using JSON input
|
# 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."]}}
|
{"detail": {"bar": ["This field is required."], "baz": ["This field is required."]}}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Object Store API
|
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.
|
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::
|
.. 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::
|
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
|
URL configuration
|
||||||
|
@ -77,13 +77,13 @@ For example if we make a POST request using form input:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. 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."]}}
|
{"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:
|
Or if we make the same request using JSON:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. 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."]}}
|
{"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:
|
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::
|
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:
|
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:
|
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:
|
And from the command line:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# Demonstrates API's input validation using form input
|
# 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."]}}
|
{"detail": {"bar": ["This field is required."], "baz": ["This field is required."]}}
|
||||||
|
|
||||||
# Demonstrates API's input validation using JSON input
|
# 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."]}}
|
{"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:
|
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::
|
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
|
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.
|
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:
|
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/>`_.
|
* 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.
|
* 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.
|
* 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:
|
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.)
|
(The :doc:`examples/sandbox` resource is also documented.)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user