Merge branch 'master' into 2.4.0

This commit is contained in:
Tom Christie 2013-07-04 20:31:26 +01:00
commit 9e4e2c60f7
18 changed files with 251 additions and 42 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
.* .*
html/ html/
htmlcov/
coverage/ coverage/
build/ build/
dist/ dist/

View File

@ -355,6 +355,10 @@ HTTP digest authentication is a widely implemented scheme that was intended to r
The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by [Evonove][evonove] and uses the excelllent [OAuthLib][oauthlib]. The package is well documented, and comes as a recommended alternative for OAuth 2.0 support. The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by [Evonove][evonove] and uses the excelllent [OAuthLib][oauthlib]. The package is well documented, and comes as a recommended alternative for OAuth 2.0 support.
## Django OAuth2 Consumer
The [Django OAuth2 Consumer][doac] library from [Rediker Software][rediker] is another package that provides [OAuth 2.0 support for REST framework][doac-rest-framework]. The package includes token scoping permissions on tokens, which allows finer-grained access to your API.
[cite]: http://jacobian.org/writing/rest-worst-practices/ [cite]: http://jacobian.org/writing/rest-worst-practices/
[http401]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 [http401]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
[http403]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4 [http403]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4
@ -376,3 +380,6 @@ The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 supp
[django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit [django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit
[evonove]: https://github.com/evonove/ [evonove]: https://github.com/evonove/
[oauthlib]: https://github.com/idan/oauthlib [oauthlib]: https://github.com/idan/oauthlib
[doac]: https://github.com/Rediker-Software/doac
[rediker]: https://github.com/Rediker-Software
[doac-rest-framework]: https://github.com/Rediker-Software/doac/blob/master/docs/markdown/integrations.md#

View File

@ -98,7 +98,23 @@ As with `SimpleRouter` the trailing slashs on the URL routes can be removed by s
Implementing a custom router isn't something you'd need to do very often, but it can be useful if you have specific requirements about how the your URLs for your API are strutured. Doing so allows you to encapsulate the URL structure in a reusable way that ensures you don't have to write your URL patterns explicitly for each new view. Implementing a custom router isn't something you'd need to do very often, but it can be useful if you have specific requirements about how the your URLs for your API are strutured. Doing so allows you to encapsulate the URL structure in a reusable way that ensures you don't have to write your URL patterns explicitly for each new view.
The simplest way to implement a custom router is to subclass one of the existing router classes. The `.routes` attribute is used to template the URL patterns that will be mapped to each viewset. The simplest way to implement a custom router is to subclass one of the existing router classes. The `.routes` attribute is used to template the URL patterns that will be mapped to each viewset. The `.routes` attribute is a list of `Route` named tuples.
The arguments to the `Route` named tuple are:
**url**: A string representing the URL to be routed. May include the following format strings:
* `{prefix}` - The URL prefix to use for this set of routes.
* `{lookup}` - The lookup field used to match against a single instance.
* `{trailing_slash}` - Either a '/' or an empty string, depending on the `trailing_slash` argument.
**mapping**: A mapping of HTTP method names to the view methods
**name**: The name of the URL as used in `reverse` calls. May include the following format string:
* `{basename}` - The base to use for the URL names that are created.
**initkwargs**: A dictionary of any additional arguments that should be passed when instantiating the view. Note that the `suffix` argument is reserved for identifying the viewset type, used when generating the view name and breadcrumb links.
## Example ## Example
@ -106,13 +122,21 @@ The following example will only route to the `list` and `retrieve` actions, and
class ReadOnlyRouter(SimpleRouter): class ReadOnlyRouter(SimpleRouter):
""" """
A router for read-only APIs, which doesn't use trailing suffixes. A router for read-only APIs, which doesn't use trailing slashes.
""" """
routes = [ routes = [
(r'^{prefix}$', {'get': 'list'}, '{basename}-list'), Route(url=r'^{prefix}$',
(r'^{prefix}/{lookup}$', {'get': 'retrieve'}, '{basename}-detail') mapping={'get': 'list'},
name='{basename}-list',
initkwargs={'suffix': 'List'}),
Route(url=r'^{prefix}/{lookup}$',
mapping={'get': 'retrieve'},
name='{basename}-detail',
initkwargs={'suffix': 'Detail'})
] ]
The `SimpleRouter` class provides another example of setting the `.routes` attribute.
## Advanced custom routers ## Advanced custom routers
If you want to provide totally custom behavior, you can override `BaseRouter` and override the `get_urls(self)` method. The method should insect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the `self.registry` attribute. If you want to provide totally custom behavior, you can override `BaseRouter` and override the `get_urls(self)` method. The method should insect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the `self.registry` attribute.

View File

@ -423,6 +423,49 @@ You can create customized subclasses of `ModelSerializer` or `HyperlinkedModelSe
Doing so should be considered advanced usage, and will only be needed if you have some particular serializer requirements that you often need to repeat. Doing so should be considered advanced usage, and will only be needed if you have some particular serializer requirements that you often need to repeat.
## Dynamically modifiying fields
Once a serializer has been initialized, the dictionary of fields that are set on the serializer may be accessed using the `.fields` attribute. Accessing and modifying this attribute allows you to dynamically modify the serializer.
Modifying the `fields` argument directly allows you to do interesting things such as changing the arguments on serializer fields at runtime, rather than at the point of declaring the serializer.
### Example
For example, if you wanted to be able to set which fields should be used by a serializer at the point of initializing it, you could create a serializer class like so:
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed.
"""
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instatiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields.keys())
for field_name in existing - allowed:
self.fields.pop(field_name)
This would then allow you to do the following:
>>> class UserSerializer(DynamicFieldsModelSerializer):
>>> class Meta:
>>> model = User
>>> fields = ('id', 'username', 'email')
>>>
>>> print UserSerializer(user)
{'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'}
>>>
>>> print UserSerializer(user, fields=('id', 'email'))
{'id': 2, 'email': 'jon@example.com'}
## Customising the default fields ## Customising the default fields
The `field_mapping` attribute is a dictionary that maps model classes to serializer classes. Overriding the attribute will let you set a different set of default serializer classes. The `field_mapping` attribute is a dictionary that maps model classes to serializer classes. Overriding the attribute will let you set a different set of default serializer classes.
@ -457,7 +500,7 @@ Note that the `model_field` argument will be `None` for reverse relationships.
Returns the field instance that should be used for non-relational, non-pk fields. Returns the field instance that should be used for non-relational, non-pk fields.
## Example ### Example
The following custom model serializer could be used as a base class for model serializers that should always exclude the pk by default. The following custom model serializer could be used as a base class for model serializers that should always exclude the pk by default.

BIN
docs/img/apiary.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
docs/img/cerulean.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/img/slate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -170,6 +170,7 @@ The API guide is your complete reference manual to all the functionality provide
General guides to using REST framework. General guides to using REST framework.
* [Documenting your API][documenting-your-api]
* [AJAX, CSRF & CORS][ajax-csrf-cors] * [AJAX, CSRF & CORS][ajax-csrf-cors]
* [Browser enhancements][browser-enhancements] * [Browser enhancements][browser-enhancements]
* [The Browsable API][browsableapi] * [The Browsable API][browsableapi]
@ -289,6 +290,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[status]: api-guide/status-codes.md [status]: api-guide/status-codes.md
[settings]: api-guide/settings.md [settings]: api-guide/settings.md
[documenting-your-api]: topics/documenting-your-api.md
[ajax-csrf-cors]: topics/ajax-csrf-cors.md [ajax-csrf-cors]: topics/ajax-csrf-cors.md
[browser-enhancements]: topics/browser-enhancements.md [browser-enhancements]: topics/browser-enhancements.md
[browsableapi]: topics/browsable-api.md [browsableapi]: topics/browsable-api.md

View File

@ -95,6 +95,7 @@
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="{{ base_url }}/topics/documenting-your-api{{ suffix }}">Documenting your API</a></li>
<li><a href="{{ base_url }}/topics/ajax-csrf-cors{{ suffix }}">AJAX, CSRF & CORS</a></li> <li><a href="{{ base_url }}/topics/ajax-csrf-cors{{ suffix }}">AJAX, CSRF & CORS</a></li>
<li><a href="{{ base_url }}/topics/browser-enhancements{{ suffix }}">Browser enhancements</a></li> <li><a href="{{ base_url }}/topics/browser-enhancements{{ suffix }}">Browser enhancements</a></li>
<li><a href="{{ base_url }}/topics/browsable-api{{ suffix }}">The Browsable API</a></li> <li><a href="{{ base_url }}/topics/browsable-api{{ suffix }}">The Browsable API</a></li>

View File

@ -11,69 +11,85 @@ API may stand for Application *Programming* Interface, but humans have to be abl
If you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The `rest_framework` package includes a [`reverse`][drfreverse] helper for this purpose. If you include fully-qualified URLs in your resource output, they will be 'urlized' and made clickable for easy browsing by humans. The `rest_framework` package includes a [`reverse`][drfreverse] helper for this purpose.
## Formats ## Formats
By default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using `?format=` in the request, so you can look at the raw JSON response in a browser by adding `?format=json` to the URL. There are helpful extensions for viewing JSON in [Firefox][ffjsonview] and [Chrome][chromejsonview]. By default, the API will return the format specified by the headers, which in the case of the browser is HTML. The format can be specified using `?format=` in the request, so you can look at the raw JSON response in a browser by adding `?format=json` to the URL. There are helpful extensions for viewing JSON in [Firefox][ffjsonview] and [Chrome][chromejsonview].
## Customizing ## Customizing
To customize the look-and-feel, create a template called `api.html` and add it to your project, eg: `templates/rest_framework/api.html`, that extends the `rest_framework/base.html` template. The browsable API is built with [Twitter's Bootstrap][bootstrap] (v 2.1.1), making it easy to customize the look-and-feel.
The included browsable API template is built with [Bootstrap (2.1.1)][bootstrap], making it easy to customize the look-and-feel. To customize the default style, create a template called `rest_framework/api.html` that extends from `rest_framework/base.html`. For example:
### Theme **templates/rest_framework/api.html**
To replace the theme wholesale, add a `bootstrap_theme` block to your `api.html` and insert a `link` to the desired Bootstrap theme css file. This will completely replace the included theme. {% extends "rest_framework/base.html" %}
... # Override blocks with required customizations
### Overriding the default theme
To replace the default theme, add a `bootstrap_theme` block to your `api.html` and insert a `link` to the desired Bootstrap theme css file. This will completely replace the included theme.
{% block bootstrap_theme %} {% block bootstrap_theme %}
<link rel="stylesheet" href="/path/to/my/bootstrap.css" type="text/css"> <link rel="stylesheet" href="/path/to/my/bootstrap.css" type="text/css">
{% endblock %} {% endblock %}
A suitable replacement theme can be generated using Bootstrap's [Customize Tool][bcustomize]. Also, there are pre-made themes available at [Bootswatch][bswatch]. To use any of the Bootswatch themes, simply download the theme's `bootstrap.min.css` file, add it to your project, and replace the default one as described above. A suitable replacement theme can be generated using Bootstrap's [Customize Tool][bcustomize]. There are also pre-made themes available at [Bootswatch][bswatch]. To use any of the Bootswatch themes, simply download the theme's `bootstrap.min.css` file, add it to your project, and replace the default one as described above.
You can also change the navbar variant, which by default is `navbar-inverse`, using the `bootstrap_navbar_variant` block. The empty `{% block bootstrap_navbar_variant %}{% endblock %}` will use the original Bootstrap navbar style. You can also change the navbar variant, which by default is `navbar-inverse`, using the `bootstrap_navbar_variant` block. The empty `{% block bootstrap_navbar_variant %}{% endblock %}` will use the original Bootstrap navbar style.
Full Example Full example:
{% extends "rest_framework/base.html" %} {% extends "rest_framework/base.html" %}
{% block bootstrap_theme %} {% block bootstrap_theme %}
<link rel="stylesheet" href="/path/to/yourtheme/bootstrap.min.css' type="text/css"> <link rel="stylesheet" href="http://bootswatch.com/flatly/bootstrap.min.css" type="text/css">
{% endblock %} {% endblock %}
{% block bootstrap_navbar_variant %}{% endblock %} {% block bootstrap_navbar_variant %}{% endblock %}
For more specific CSS tweaks than simply overriding the default bootstrap theme you can override the `style` block.
For more specific CSS tweaks, use the `style` block instead. ---
![Cerulean theme][cerulean]
*Screenshot of the bootswatch 'Cerulean' theme*
---
![Slate theme][slate]
*Screenshot of the bootswatch 'Slate' theme*
---
### Blocks ### Blocks
All of the blocks available in the browsable API base template that can be used in your `api.html`. All of the blocks available in the browsable API base template that can be used in your `api.html`.
* `bodyclass` - (empty) class attribute for the `<body>` * `bodyclass` - Class attribute for the `<body>` tag, empty by default.
* `bootstrap_theme` - CSS for the Bootstrap theme * `bootstrap_theme` - CSS for the Bootstrap theme.
* `bootstrap_navbar_variant` - CSS class for the navbar * `bootstrap_navbar_variant` - CSS class for the navbar.
* `branding` - section of the navbar, see [Bootstrap components][bcomponentsnav] * `branding` - Branding section of the navbar, see [Bootstrap components][bcomponentsnav].
* `breadcrumbs` - Links showing resource nesting, allowing the user to go back up the resources. It's recommended to preserve these, but they can be overridden using the breadcrumbs block. * `breadcrumbs` - Links showing resource nesting, allowing the user to go back up the resources. It's recommended to preserve these, but they can be overridden using the breadcrumbs block.
* `footer` - Any copyright notices or similar footer materials can go here (by default right-aligned) * `footer` - Any copyright notices or similar footer materials can go here (by default right-aligned).
* `style` - CSS stylesheets for the page * `style` - CSS stylesheets for the page.
* `title` - title of the page * `title` - Title of the page.
* `userlinks` - This is a list of links on the right of the header, by default containing login/logout links. To add links instead of replace, use {{ block.super }} to preserve the authentication links. * `userlinks` - This is a list of links on the right of the header, by default containing login/logout links. To add links instead of replace, use `{{ block.super }}` to preserve the authentication links.
#### Components #### Components
All of the [Bootstrap components][bcomponents] are available. All of the standard [Bootstrap components][bcomponents] are available.
##### Tooltips #### Tooltips
The browsable API makes use of the Bootstrap tooltips component. Any element with the `js-tooltip` class and a `title` attribute has that title content displayed in a tooltip on hover after a 1000ms delay. The browsable API makes use of the Bootstrap tooltips component. Any element with the `js-tooltip` class and a `title` attribute has that title content will display a tooltip on hover events.
### Login Template ### Login Template
To add branding and customize the look-and-feel of the auth login template, create a template called `login.html` and add it to your project, eg: `templates/rest_framework/login.html`, that extends the `rest_framework/base_login.html` template. To add branding and customize the look-and-feel of the login template, create a template called `login.html` and add it to your project, eg: `templates/rest_framework/login.html`. The template should extend from `rest_framework/base_login.html`.
You can add your site name or branding by including the branding block: You can add your site name or branding by including the branding block:
@ -114,6 +130,8 @@ For more advanced customization, such as not having a Bootstrap basis or tighter
[ffjsonview]: https://addons.mozilla.org/en-US/firefox/addon/jsonview/ [ffjsonview]: https://addons.mozilla.org/en-US/firefox/addon/jsonview/
[chromejsonview]: https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc [chromejsonview]: https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc
[bootstrap]: http://getbootstrap.com [bootstrap]: http://getbootstrap.com
[cerulean]: ../img/cerulean.png
[slate]: ../img/slate.png
[bcustomize]: http://twitter.github.com/bootstrap/customize.html#variables [bcustomize]: http://twitter.github.com/bootstrap/customize.html#variables
[bswatch]: http://bootswatch.com/ [bswatch]: http://bootswatch.com/
[bcomponents]: http://twitter.github.com/bootstrap/components.html [bcomponents]: http://twitter.github.com/bootstrap/components.html

View File

@ -144,6 +144,7 @@ The following people have helped make REST framework great.
* David Sanders - [davesque] * David Sanders - [davesque]
* Philip Douglas - [freakydug] * Philip Douglas - [freakydug]
* Igor Kalat - [trwired] * Igor Kalat - [trwired]
* Rudolf Olah - [omouse]
Many thanks to everyone who's contributed to the project. Many thanks to everyone who's contributed to the project.
@ -324,3 +325,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter.
[davesque]: https://github.com/davesque [davesque]: https://github.com/davesque
[freakydug]: https://github.com/freakydug [freakydug]: https://github.com/freakydug
[trwired]: https://github.com/trwired [trwired]: https://github.com/trwired
[omouse]: https://github.com/omouse

View File

@ -0,0 +1,112 @@
# Documenting your API
> A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state.
>
> &mdash; Roy Fielding, [REST APIs must be hypertext driven][cite]
There are a variety of approaches to API documentation. This document introduces a few of the various tools and options you might choose from. The approaches should not be considered exclusive - you may want to provide more than one documentation style for you API, such as a self describing API that also includes static documentation of the various API endpoints.
## Endpoint documentation
The most common way to document Web APIs today is to produce documentation that lists the API endpoints verbatim, and describes the allowable operations on each. There are various tools that allow you to do this in an automated or semi-automated way.
---
#### Django REST Swagger
Marc Gibbons' [Django REST Swagger][django-rest-swagger] integrates REST framework with the [Swagger][swagger] API documentation tool. The package produces well presented API documentation, and includes interactive tools for testing API endpoints.
The pacakge is fully documented, well supported, and comes highly recommended.
Django REST Swagger supports REST framework versions 2.3 and above.
![Screenshot - Django REST Swagger][image-django-rest-swagger]
---
#### REST Framework Docs
The [REST Framework Docs][rest-framework-docs] package is an earlier project, also by Marc Gibbons, that offers clean, simple autogenerated documentation for your API.
![Screenshot - REST Framework Docs][image-rest-framework-docs]
---
#### Apiary
There are various other online tools and services for providing API documentation. One notable service is [Apiary][apiary]. With Apiary, you describe your API using a simple markdown-like syntax. The generated documentation includes API interaction, a mock server for testing & prototyping, and various other tools.
![Screenshot - Apiary][image-apiary]
---
## Self describing APIs
The browsable API that REST framwork provides makes it possible for your API to be entirely self describing. The documentation for each API endpoint can be provided simply by visiting the URL in your browser.
![Screenshot - Self describing API][image-self-describing-api]
---
#### Setting the title
The title that is used in the browsable API is generated from the view class name or function name. Any trailing `View` or `ViewSet` suffix is stripped, and the string is whitespace separated on uppercase/lowercase boundaries or underscores.
For example, the view `UserListView`, will be named `User List` when presented in the browsable API.
When working with viewsets, an appropriate suffix is appended to each generated view. For example, the view set `UserViewSet` will generate views named `User List` and `User Instance`.
#### Setting the description
The description in the browsable API is generated from the docstring of the view or viewset.
If the python `markdown` library is installed, then [markdown syntax][markdown] may be used in the docstring, and will be converted to HTML in the browsable API. For example:
class AccountListView(views.APIView):
"""
Returns a list of all **active** accounts in the system.
For more details on how accounts are activated please [see here][ref].
[ref]: http://example.com/activating-accounts
"""
Note that one constraint of using viewsets is that any documentation be used for all generated views, so for example, you cannot have differing documentation for the generated list view and detail view.
#### The `OPTIONS` method
REST framework APIs also support programmatically accessible descriptions, using the `OPTIONS` HTTP method. A view will respond to an `OPTIONS` request with metadata including the name, description, and the various media types it accepts and responds with.
When using the generic views, any `OPTIONS` requests will additionally respond with metadata regarding any `POST` or `PUT` actions available, describing which fields are on the serializer.
You can modify the response behavior to `OPTIONS` requests by overriding the `metadata` view method. For example:
def metadata(self, request):
"""
Don't include the view description in OPTIONS responses.
"""
data = super(ExampleView, self).metadata(request)
data.pop('description')
return data
---
## The hypermedia approach
To be fully RESTful an API should present it's available actions as hypermedia controls in the responses that it sends.
In this approach, rather than documenting the available API endpoints up front, the description instead concentrates on the *media types* that are used. The available actions take may be taken on any given URL are not strictly fixed, but are instead made available by the presence of link and form controls in the returned document.
To implement a hypermedia API you'll need to decide on an appropriate media type for the API, and implement a custom renderer and parser for that media type. The [REST, Hypermedia & HATEOAS][hypermedia-docs] section of the documention includes pointers to background reading, as well as links to various hypermedia formats.
[cite]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
[django-rest-swagger]: https://github.com/marcgibbons/django-rest-swagger
[swagger]: https://developers.helloreverb.com/swagger/
[rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs
[apiary]: http://apiary.io/
[markdown]: http://daringfireball.net/projects/markdown/
[hypermedia-docs]: rest-hypermedia-hateoas.md
[image-django-rest-swagger]: ../img/django-rest-swagger.png
[image-rest-framework-docs]: ../img/rest-framework-docs.png
[image-apiary]: ../img/apiary.png
[image-self-describing-api]: ../img/self-describing.png

View File

@ -32,7 +32,7 @@ REST framework also includes [serialization] and [parser]/[renderer] components
## What REST framework doesn't provide. ## What REST framework doesn't provide.
What REST framework doesn't do is give you is machine readable hypermedia formats such as [HAL][hal], [Collection+JSON][collection] or HTML [microformats] by default, or the ability to auto-magically create fully HATEOAS style APIs that include hypermedia-based form descriptions and semantically labelled hyperlinks. Doing so would involve making opinionated choices about API design that should really remain outside of the framework's scope. What REST framework doesn't do is give you is machine readable hypermedia formats such as [HAL][hal], [Collection+JSON][collection], [JSON API][json-api] or HTML [microformats] by default, or the ability to auto-magically create fully HATEOAS style APIs that include hypermedia-based form descriptions and semantically labelled hyperlinks. Doing so would involve making opinionated choices about API design that should really remain outside of the framework's scope.
[cite]: http://vimeo.com/channels/restfest/page:2 [cite]: http://vimeo.com/channels/restfest/page:2
[dissertation]: http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm [dissertation]: http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
@ -46,6 +46,7 @@ What REST framework doesn't do is give you is machine readable hypermedia format
[hal]: http://stateless.co/hal_specification.html [hal]: http://stateless.co/hal_specification.html
[collection]: http://www.amundsen.com/media-types/collection/ [collection]: http://www.amundsen.com/media-types/collection/
[json-api]: http://jsonapi.org/
[microformats]: http://microformats.org/wiki/Main_Page [microformats]: http://microformats.org/wiki/Main_Page
[serialization]: ../api-guide/serializers.md [serialization]: ../api-guide/serializers.md
[parser]: ../api-guide/parsers.md [parser]: ../api-guide/parsers.md

View File

@ -70,6 +70,7 @@ path_list = [
'api-guide/exceptions.md', 'api-guide/exceptions.md',
'api-guide/status-codes.md', 'api-guide/status-codes.md',
'api-guide/settings.md', 'api-guide/settings.md',
'topics/documenting-your-api.md',
'topics/ajax-csrf-cors.md', 'topics/ajax-csrf-cors.md',
'topics/browser-enhancements.md', 'topics/browser-enhancements.md',
'topics/browsable-api.md', 'topics/browsable-api.md',

View File

@ -50,10 +50,7 @@ class JSONParser(BaseParser):
def parse(self, stream, media_type=None, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
""" """
Returns a 2-tuple of `(data, files)`. Parses the incoming bytestream as JSON and returns the resulting data.
`data` will be an object which is the parsed content of the response.
`files` will always be `None`.
""" """
parser_context = parser_context or {} parser_context = parser_context or {}
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
@ -74,10 +71,7 @@ class YAMLParser(BaseParser):
def parse(self, stream, media_type=None, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
""" """
Returns a 2-tuple of `(data, files)`. Parses the incoming bytestream as YAML and returns the resulting data.
`data` will be an object which is the parsed content of the response.
`files` will always be `None`.
""" """
assert yaml, 'YAMLParser requires pyyaml to be installed' assert yaml, 'YAMLParser requires pyyaml to be installed'
@ -100,10 +94,8 @@ class FormParser(BaseParser):
def parse(self, stream, media_type=None, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
""" """
Returns a 2-tuple of `(data, files)`. Parses the incoming bytestream as a URL encoded form,
and returns the resulting QueryDict.
`data` will be a :class:`QueryDict` containing all the form parameters.
`files` will always be :const:`None`.
""" """
parser_context = parser_context or {} parser_context = parser_context or {}
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
@ -120,7 +112,8 @@ class MultiPartParser(BaseParser):
def parse(self, stream, media_type=None, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
""" """
Returns a DataAndFiles object. Parses the incoming bytestream as a multipart encoded form,
and returns a DataAndFiles object.
`.data` will be a `QueryDict` containing all the form parameters. `.data` will be a `QueryDict` containing all the form parameters.
`.files` will be a `QueryDict` containing all the form files. `.files` will be a `QueryDict` containing all the form files.
@ -147,6 +140,9 @@ class XMLParser(BaseParser):
media_type = 'application/xml' media_type = 'application/xml'
def parse(self, stream, media_type=None, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
"""
Parses the incoming bytestream as XML and returns the resulting data.
"""
assert etree, 'XMLParser requires defusedxml to be installed' assert etree, 'XMLParser requires defusedxml to be installed'
parser_context = parser_context or {} parser_context = parser_context or {}
@ -216,7 +212,8 @@ class FileUploadParser(BaseParser):
def parse(self, stream, media_type=None, parser_context=None): def parse(self, stream, media_type=None, parser_context=None):
""" """
Returns a DataAndFiles object. Treats the incoming bytestream as a raw file upload and returns
a `DateAndFiles` object.
`.data` will be None (we expect request body to be a file content). `.data` will be None (we expect request body to be a file content).
`.files` will be a `QueryDict` containing one 'file' element. `.files` will be a `QueryDict` containing one 'file' element.