diff options
Diffstat (limited to 'docs/api-guide/renderers.md')
| -rw-r--r-- | docs/api-guide/renderers.md | 138 |
1 files changed, 93 insertions, 45 deletions
diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index b2ebd0c7..c3d12ddb 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -6,7 +6,7 @@ > > — [Django documentation][cite] -REST framework includes a number of built in Renderer classes, that allow you to return responses with various media types. There is also support for defining your own custom renderers, which gives you the flexiblity to design your own media types. +REST framework includes a number of built in Renderer classes, that allow you to return responses with various media types. There is also support for defining your own custom renderers, which gives you the flexibility to design your own media types. ## How the renderer is determined @@ -18,10 +18,10 @@ For more information see the documentation on [content negotation][conneg]. ## Setting the renderers -The default set of renderers may be set globally, using the `DEFAULT_RENDERERS` setting. For example, the following settings would use `YAML` as the main media type and also include the self describing API. +The default set of renderers may be set globally, using the `DEFAULT_RENDERER_CLASSES` setting. For example, the following settings would use `YAML` as the main media type and also include the self describing API. REST_FRAMEWORK = { - 'DEFAULT_RENDERERS': ( + 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.YAMLRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ) @@ -42,8 +42,8 @@ You can also set the renderers used for an individual view, using the `APIView` Or, if you're using the `@api_view` decorator with function based views. - @api_view('GET'), - @renderer_classes(JSONRenderer, JSONPRenderer) + @api_view(['GET']) + @renderer_classes((JSONRenderer, JSONPRenderer)) def user_count_view(request, format=None): """ A view that returns the count of active users, in JSON or JSONp. @@ -66,34 +66,52 @@ If your API includes views that can serve both regular webpages and API response ## JSONRenderer -**.media_type:** `application/json` +Renders the request data into `JSON`. -**.format:** `'.json'` +The client may additionally include an `'indent'` media type parameter, in which case the returned `JSON` will be indented. For example `Accept: application/json; indent=4`. + +**.media_type**: `application/json` + +**.format**: `'.json'` ## JSONPRenderer -**.media_type:** `application/javascript` +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'`. -**.format:** `'.jsonp'` +**Note**: If you require cross-domain AJAX requests, you may also want to consider using [CORS] as an alternative to `JSONP`. + +**.media_type**: `application/javascript` + +**.format**: `'.jsonp'` ## YAMLRenderer -**.media_type:** `application/yaml` +Renders the request data into `YAML`. + +**.media_type**: `application/yaml` -**.format:** `'.yaml'` +**.format**: `'.yaml'` ## XMLRenderer -**.media_type:** `application/xml` +Renders REST framework's default style of `XML` response content. -**.format:** `'.xml'` +Note that the `XML` markup language is used typically used as the base language for more strictly defined domain-specific languages, such as `RSS`, `Atom`, and `XHTML`. -## HTMLRenderer +If you are considering using `XML` for your API, you may want to consider implementing a custom renderer and parser for your specific requirements, and using an existing domain-specific media-type, or creating your own custom XML-based media-type. + +**.media_type**: `application/xml` + +**.format**: `'.xml'` + +## TemplateHTMLRenderer Renders data to HTML, using Django's standard template rendering. Unlike other renderers, the data passed to the `Response` does not need to be serialized. Also, unlike other renderers, you may want to include a `template_name` argument when creating the `Response`. -The HTMLRenderer will create a `RequestContext`, using the `response.data` as the context dict, and determine a template name to use to render the context. +The TemplateHTMLRenderer will create a `RequestContext`, using the `response.data` as the context dict, and determine a template name to use to render the context. The template name is determined by (in order of preference): @@ -101,40 +119,84 @@ The template name is determined by (in order of preference): 2. An explicit `.template_name` attribute set on this class. 3. The return result of calling `view.get_template_names()`. -An example of a view that uses `HTMLRenderer`: +An example of a view that uses `TemplateHTMLRenderer`: class UserInstance(generics.RetrieveUserAPIView): """ A view that returns a templated HTML representations of a given user. """ model = Users - renderer_classes = (HTMLRenderer,) + renderer_classes = (TemplateHTMLRenderer,) def get(self, request, *args, **kwargs) self.object = self.get_object() - return Response(self.object, template_name='user_detail.html') + return Response({'user': self.object}, template_name='user_detail.html') -You can use `HTMLRenderer` either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint. +You can use `TemplateHTMLRenderer` either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint. + +If you're building websites that use `TemplateHTMLRenderer` along with other renderer classes, you should consider listing `TemplateHTMLRenderer` as the first class in the `renderer_classes` list, so that it will be prioritised first even for browsers that send poorly formed `ACCEPT:` headers. + +**.media_type**: `text/html` + +**.format**: `'.html'` -If you're building websites that use `HTMLRenderer` along with other renderer classes, you should consider listing `HTMLRenderer` as the first class in the `renderer_classes` list, so that it will be prioritised first even for browsers that send poorly formed `ACCEPT:` headers. +See also: `StaticHTMLRenderer` -**.media_type:** `text/html` +## StaticHTMLRenderer -**.format:** `'.html'` +A simple renderer that simply returns pre-rendered HTML. Unlike other renderers, the data passed to the response object should be a string representing the content to be returned. + +An example of a view that uses `TemplateHTMLRenderer`: + + @api_view(('GET',)) + @renderer_classes((StaticHTMLRenderer,)) + def simple_html_view(request): + data = '<html><body><h1>Hello, world</h1></body></html>' + return Response(data) + +You can use `TemplateHTMLRenderer` either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint. + +**.media_type**: `text/html` + +**.format**: `'.html'` + +See also: `TemplateHTMLRenderer` ## BrowsableAPIRenderer Renders data into HTML for the Browseable API. This renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page. -**.media_type:** `text/html` +**.media_type**: `text/html` + +**.format**: `'.api'` -**.format:** `'.api'` +--- -## Custom renderers +# Custom renderers To implement a custom renderer, you should override `BaseRenderer`, set the `.media_type` and `.format` properties, and implement the `.render(self, data, media_type=None, renderer_context=None)` method. -For example: +The arguments passed to the `.render()` method are: + +### `data` + +The request data, as set by the `Response()` instantiation. + +### `media_type=None` + +Optional. If provided, this is the accepted media type, as determined by the content negotiation stage. + +Depending on the client's `Accept:` header, this may be more specific than the renderer's `media_type` attribute, and may include media type parameters. For example `"application/json; nested=true"`. + +### `renderer_context=None` + +Optional. If provided, this is a dictionary of contextual information provided by the view. + +By default this will include the following keys: `view`, `request`, `response`, `args`, `kwargs`. + +## Example + +The following is an example plaintext renderer that will return a response with the `data` parameter as the content of the response. from django.utils.encoding import smart_unicode from rest_framework import renderers @@ -149,21 +211,6 @@ For example: return data return smart_unicode(data) -The arguments passed to the `.render()` method are: - -#### `data` - -The request data, as set by the `Response()` instantiation. - -#### `media_type=None` - -Optional. If provided, this is the accepted media type, as determined by the content negotiation stage. Depending on the client's `Accept:` header, this may be more specific than the renderer's `media_type` attribute, and may include media type parameters. For example `"application/json; nested=true"`. - -#### `renderer_context=None` - -Optional. If provided, this is a dictionary of contextual information provided by the view. -By default this will include the following keys: `view`, `request`, `response`, `args`, `kwargs`. - --- # Advanced renderer usage @@ -182,7 +229,7 @@ In some cases you might want your view to use different serialization styles dep For example: @api_view(('GET',)) - @renderer_classes((HTMLRenderer, JSONRenderer)) + @renderer_classes((TemplateHTMLRenderer, JSONRenderer)) def list_users(request): """ A view that can return JSON or HTML representations @@ -190,9 +237,9 @@ For example: """ queryset = Users.objects.filter(active=True) - if request.accepted_media_type == 'text/html': + if request.accepted_renderer.format == 'html': # TemplateHTMLRenderer takes a context dict, - # and additionally requiresa 'template_name'. + # and additionally requires a 'template_name'. # It does not require serialization. data = {'users': queryset} return Response(data, template_name='list_users.html') @@ -204,7 +251,7 @@ For example: ## Designing your media types -For the purposes of many Web APIs, simple `JSON` responses with hyperlinked relations may be sufficient. If you want to fully embrace RESTful design and [HATEOAS] you'll neeed to consider the design and usage of your media types in more detail. +For the purposes of many Web APIs, simple `JSON` responses with hyperlinked relations may be sufficient. If you want to fully embrace RESTful design and [HATEOAS] you'll need to consider the design and usage of your media types in more detail. In [the words of Roy Fielding][quote], "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, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types.". @@ -213,6 +260,7 @@ For good examples of custom media types, see GitHub's use of a custom [applicati [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 +[CORS]: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing [HATEOAS]: http://timelessrepo.com/haters-gonna-hateoas [quote]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven [application/vnd.github+json]: http://developer.github.com/v3/media/ |
