From 7367bd53a908474f14f0f44f3744f2fcb1f4111c Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Fri, 12 Oct 2012 10:02:21 +0200 Subject: Fix tiny typo --- docs/tutorial/quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 85411378..851db3c7 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -27,7 +27,7 @@ Notice that we're using hyperlinked relations in this case, with `HyperlinkedMod ## Views -Right, we'd better right some views then. Open `quickstart/views.py` and get typing. +Right, we'd better write some views then. Open `quickstart/views.py` and get typing. from django.contrib.auth.models import User, Group from rest_framework import generics -- cgit v1.2.3 From 7608cf1193fd555f31eb9a3d98c6f258720f8022 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 13 Oct 2012 15:07:43 +0100 Subject: Improve documentation for Requests --- docs/api-guide/requests.md | 101 ++++++++++++++++++++++++++---------- docs/index.md | 4 +- docs/template.html | 2 +- docs/topics/browser-enhancements.md | 43 +++++++++++++++ docs/topics/browserhacks.md | 43 --------------- 5 files changed, 121 insertions(+), 72 deletions(-) create mode 100644 docs/topics/browser-enhancements.md delete mode 100644 docs/topics/browserhacks.md (limited to 'docs') diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md index 36513cd9..919e410a 100644 --- a/docs/api-guide/requests.md +++ b/docs/api-guide/requests.md @@ -6,63 +6,112 @@ > > — Malcom Tredinnick, [Django developers group][cite] -REST framework's `Request` class extends the standard `HttpRequest`, adding support for parsing multiple content types, allowing browser-based `PUT`, `DELETE` and other methods, and adding flexible per-request authentication. +REST framework's `Request` class extends the standard `HttpRequest`, adding support for REST framework's flexible request parsing and request authentication. -## .method +--- -`request.method` returns the uppercased string representation of the request's HTTP method. +# Request parsing -Browser-based `PUT`, `DELETE` and other requests are supported, and can be made by using a hidden form field named `_method` in a regular `POST` form. +REST framework's Request objects provide flexible request parsing that allows you to treat requests with JSON data or other media types in the same way that you would normally deal with form data. +## .DATA +`request.DATA` returns the parsed content of the request body. This is similar to the standard `request.POST` attribute except that: -## .content_type +* It supports parsing the content of HTTP methods other than `POST`, meaning that you can access the content of `PUT` and `PATCH` requests. +* It supports REST framework's flexible request parsing, rather than just supporting form data. For example you can handle incoming JSON data in the same way that you handle incoming form data. -`request.content`, returns a string object representing the mimetype of the HTTP request's body, if one exists. +For more details see the [parsers documentation]. +## .FILES +`request.FILES` returns any uploaded files that may be present in the content of the request body. This is the same as the standard `HttpRequest` behavior, except that the same flexible request parsing that is used for `request.DATA`. -## .DATA +For more details see the [parsers documentation]. -`request.DATA` returns the parsed content of the request body. This is similar to the standard `HttpRequest.POST` attribute except that: +## .QUERY_PARAMS -1. It supports parsing the content of HTTP methods other than `POST`, meaning that you can access the content of `PUT` and `PATCH` requests. -2. It supports parsing multiple content types, rather than just form data. For example you can handle incoming json data in the same way that you handle incoming form data. +`request.QUERY_PARAMS` is a more correcly named synonym for `request.GET`. -## .FILES +For clarity inside your code, we recommend using `request.QUERY_PARAMS` instead of the usual `request.GET`, as *any* HTTP method type may include query parameters. -`request.FILES` returns any uploaded files that may be present in the content of the request body. This is the same as the standard `HttpRequest` behavior, except that the same flexible request parsing that is used for `request.DATA`. +## .parsers -This allows you to support file uploads from multiple content-types. For example you can write a parser that supports `POST`ing the raw content of a file, instead of using form-encoded file uploads. +The `APIView` class or `@api_view` decorator will ensure that this property is automatically to a list of `Parser` instances, based on the `parser_classes` set on the view or based on the `DEFAULT_PARSERS` setting. + +You won't typically need to access this property. + +--- + +**Note:** If a client sends malformed content, then accessing `request.DATA` or `request.FILES` may raise a `ParseError`. By default REST framework's `APIView` class or `@api_view` decorator will catch the error and return a `400 Bad Request` response. + +--- + +# Authentication + +REST framework provides flexbile, per-request authentication, that gives you the abilty to: + +* Use different authentication policies for different parts of your API. +* Support the use of multiple authentication policies. +* Provide both user and token information associated with the incoming request. ## .user -`request.user` returns a `django.contrib.auth.models.User` instance. +`request.user` typically returns an instance of `django.contrib.auth.models.User`, although the behavior depends on the authentication policy being used. + +If the request is unauthenticated the default value of `request.user` is an instance of `django.contrib.auth.models.AnonymousUser`. + +For more details see the [authentication documentation]. ## .auth -`request.auth` returns any additional authentication context that may not be contained in `request.user`. The exact behavior of `request.auth` depends on what authentication has been set in `request.authentication`. For many types of authentication this will simply be `None`, but it may also be an object representing a permission scope, an expiry time, or any other information that might be contained in a token-based authentication scheme. +`request.auth` returns any additional authentication context. The exact behavior of `request.auth` depends on the authentication policy being used, but it may typically be an instance of the token that the request was authenticated against. -## .parsers +If the request is unauthenticated, or if no additional context is present, the default value of `request.auth` is `None`. -`request.parsers` should be set to a list of `Parser` instances that can be used to parse the content of the request body. +For more details see the [authentication documentation]. -`request.parsers` may no longer be altered once `request.DATA`, `request.FILES` or `request.POST` have been accessed. +## .authenticators -If you're using the `rest_framework.views.View` class... **[TODO]** +The `APIView` class or `@api_view` decorator will ensure that this property is automatically to a list of `Authentication` instances, based on the `authentication_classes` set on the view or based on the `DEFAULT_AUTHENTICATORS` setting. -## .stream +You won't typically need to access this property. -`request.stream` returns a stream representing the content of the request body. +--- + +# Browser enhancments + +REST framework supports a few browser enhancments such as broser-based `PUT` and `DELETE` forms. + +## .method + +`request.method` returns the **uppercased** string representation of the request's HTTP method. + +Browser-based `PUT` and `DELETE` forms are transparently supported. -You will not typically need to access `request.stream`, unless you're writing a `Parser` class. +For more information see the [browser enhancements documentation]. -## .authentication +## .content_type + +`request.content_type`, returns a string object representing the media type of the HTTP request's body, or an empty string if no media type was provided. + +You won't typically need to directly access the request's content type, as you'll normally rely on REST framework's default request parsing behavior. + +If you do need to access the content type of the request you should use the `.content_type` property in preference to using `request.META.get('HTTP_CONTENT_TYPE')`, as it provides transparent support for browser-based non-form content. + +For more information see the [browser enhancements documentation]. + +## .stream + +`request.stream` returns a stream representing the content of the request body. -`request.authentication` should be set to a list of `Authentication` instances that can be used to authenticate the request. +You won't typically need to directly access the request's content, as you'll normally rely on REST framework's default request parsing behavior. -`request.authentication` may no longer be altered once `request.user` or `request.auth` have been accessed. +If you do need to access the raw content directly, you should use the `.stream` property in preference to using `request.content`, as it provides transparent support for browser-based non-form content. -If you're using the `rest_framework.views.View` class... **[TODO]** +For more information see the [browser enhancements documentation]. [cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion +[parsers documentation]: parsers.md +[authentication documentation]: authentication.md +[browser enhancements documentation]: ../topics/browser-enhancements.md \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index b3845521..322a7b27 100644 --- a/docs/index.md +++ b/docs/index.md @@ -99,7 +99,7 @@ The API guide is your complete reference manual to all the functionality provide General guides to using REST framework. * [CSRF][csrf] -* [Browser hacks][browserhacks] +* [Browser enhancements][browser-enhancements] * [Working with the Browsable API][browsableapi] * [REST, Hypermedia & HATEOAS][rest-hypermedia-hateoas] * [Contributing to REST framework][contributing] @@ -185,7 +185,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [settings]: api-guide/settings.md [csrf]: topics/csrf.md -[browserhacks]: topics/browserhacks.md +[browser-enhancements]: topics/browser-enhancements.md [browsableapi]: topics/browsable-api.md [rest-hypermedia-hateoas]: topics/rest-hypermedia-hateoas.md [contributing]: topics/contributing.md diff --git a/docs/template.html b/docs/template.html index 016de151..2cc52819 100644 --- a/docs/template.html +++ b/docs/template.html @@ -73,7 +73,7 @@ Topics
+ +`request.method` would return `"DELETE"`. + +## Browser based submission of non-form content + +Browser-based submission of content types other than form are supported by using form fields named `_content` and `_content_type`: + +For example, given the following form: + + + +`request.content_type` would return `"application/json"`, and `request.stream` would return `"{'count': 1}"` + +## URL based accept headers + +## URL based format suffixes + +## Doesn't HTML5 support PUT and DELETE forms? + +Nope. It was at one point intended to support `PUT` and `DELETE` forms, but was later [dropped from the spec](3). There remains [ongoing discussion](4) about adding support for `PUT` and `DELETE`, as well as how to support content types other than form-encoded data. + +[1]: http://www.amazon.com/Restful-Web-Services-Leonard-Richardson/dp/0596529260 +[2]: http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-put-or-delete-methods-work +[3]: http://www.w3.org/TR/html5-diff/#changes-2010-06-24 +[4]: http://amundsen.com/examples/put-delete-forms/ diff --git a/docs/topics/browserhacks.md b/docs/topics/browserhacks.md deleted file mode 100644 index 96cb1388..00000000 --- a/docs/topics/browserhacks.md +++ /dev/null @@ -1,43 +0,0 @@ -# Browser hacks - -> "There are two noncontroversial uses for overloaded POST. The first is to *simulate* HTTP's uniform interface for clients like web browsers that don't support PUT or DELETE" -> -> — [RESTful Web Services](1), Leonard Richardson & Sam Ruby. - -## Browser based PUT, DELETE, etc... - -**TODO: Preamble.** Note that this is the same strategy as is used in [Ruby on Rails](2). - -For example, given the following form: - - - -`request.method` would return `"DELETE"`. - -## Browser based submission of non-form content - -Browser-based submission of content types other than form are supported by using form fields named `_content` and `_content_type`: - -For example, given the following form: - - - -`request.content_type` would return `"application/json"`, and `request.content` would return `"{'count': 1}"` - -## URL based accept headers - -## URL based format suffixes - -## Doesn't HTML5 support PUT and DELETE forms? - -Nope. It was at one point intended to support `PUT` and `DELETE` forms, but was later [dropped from the spec](3). There remains [ongoing discussion](4) about adding support for `PUT` and `DELETE`, as well as how to support content types other than form-encoded data. - -[1]: http://www.amazon.com/Restful-Web-Services-Leonard-Richardson/dp/0596529260 -[2]: http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-put-or-delete-methods-work -[3]: http://www.w3.org/TR/html5-diff/#changes-2010-06-24 -[4]: http://amundsen.com/examples/put-delete-forms/ -- cgit v1.2.3 From fe5db419491fb400d4f7211f57225719087d7c36 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 13 Oct 2012 15:12:44 +0100 Subject: Fix typo --- docs/api-guide/requests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md index 919e410a..a371143a 100644 --- a/docs/api-guide/requests.md +++ b/docs/api-guide/requests.md @@ -79,7 +79,7 @@ You won't typically need to access this property. --- -# Browser enhancments +# Browser enhancements REST framework supports a few browser enhancments such as broser-based `PUT` and `DELETE` forms. -- cgit v1.2.3 From b3477b3b6c1431a03089d68828c13568d02dc990 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Sat, 13 Oct 2012 15:34:38 +0100 Subject: Docs tweaks --- docs/index.md | 2 +- docs/template.html | 2 +- docs/topics/browsable-api.md | 2 +- docs/topics/migration.md | 8 ++++++-- 4 files changed, 9 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/index.md b/docs/index.md index 322a7b27..4ccafeeb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -100,7 +100,7 @@ General guides to using REST framework. * [CSRF][csrf] * [Browser enhancements][browser-enhancements] -* [Working with the Browsable API][browsableapi] +* [The Browsable API][browsableapi] * [REST, Hypermedia & HATEOAS][rest-hypermedia-hateoas] * [Contributing to REST framework][contributing] * [2.0 Migration Guide][migration] diff --git a/docs/template.html b/docs/template.html index 2cc52819..8051fe99 100644 --- a/docs/template.html +++ b/docs/template.html @@ -74,7 +74,7 @@ diff --git a/docs/topics/changelog.md b/docs/topics/changelog.md deleted file mode 100644 index 15fb6301..00000000 --- a/docs/topics/changelog.md +++ /dev/null @@ -1,111 +0,0 @@ -# Change Log - -## 2.0.0 - -* **Fix all of the things.** -* For more information please see the [2.0 migration guide][migration]. - ---- - -## 0.4.0 - -* Supports Django 1.5. -* Fixes issues with 'HEAD' method. -* Allow views to specify template used by TemplateRenderer -* More consistent error responses -* Some serializer fixes -* Fix internet explorer ajax behaviour -* Minor xml and yaml fixes -* Improve setup (eg use staticfiles, not the defunct ADMIN_MEDIA_PREFIX) -* Sensible absolute URL generation, not using hacky set_script_prefix - -## 0.3.3 - -* Added DjangoModelPermissions class to support `django.contrib.auth` style permissions. -* Use `staticfiles` for css files. - - Easier to override. Won't conflict with customised admin styles (eg grappelli) -* Templates are now nicely namespaced. - - Allows easier overriding. -* Drop implied 'pk' filter if last arg in urlconf is unnamed. - - Too magical. Explict is better than implicit. -* Saner template variable autoescaping. -* Tider setup.py -* Updated for URLObject 2.0 -* Bugfixes: - - Bug with PerUserThrottling when user contains unicode chars. - -## 0.3.2 - -* Bugfixes: - * Fix 403 for POST and PUT from the UI with UserLoggedInAuthentication (#115) - * serialize_model method in serializer.py may cause wrong value (#73) - * Fix Error when clicking OPTIONS button (#146) - * And many other fixes -* Remove short status codes - - Zen of Python: "There should be one-- and preferably only one --obvious way to do it." -* get_name, get_description become methods on the view - makes them overridable. -* Improved model mixin API - Hooks for build_query, get_instance_data, get_model, get_queryset, get_ordering - -## 0.3.1 - -* [not documented] - -## 0.3.0 - -* JSONP Support -* Bugfixes, including support for latest markdown release - -## 0.2.4 - -* Fix broken IsAdminUser permission. -* OPTIONS support. -* XMLParser. -* Drop mentions of Blog, BitBucket. - -## 0.2.3 - -* Fix some throttling bugs. -* ``X-Throttle`` header on throttling. -* Support for nesting resources on related models. - -## 0.2.2 - -* Throttling support complete. - -## 0.2.1 - -* Couple of simple bugfixes over 0.2.0 - -## 0.2.0 - -* Big refactoring changes since 0.1.0, ask on the discussion group if anything isn't clear. - The public API has been massively cleaned up. Expect it to be fairly stable from here on in. - -* ``Resource`` becomes decoupled into ``View`` and ``Resource``, your views should now inherit from ``View``, not ``Resource``. - -* The handler functions on views ``.get() .put() .post()`` etc, no longer have the ``content`` and ``auth`` args. - Use ``self.CONTENT`` inside a view to access the deserialized, validated content. - Use ``self.user`` inside a view to access the authenticated user. - -* ``allowed_methods`` and ``anon_allowed_methods`` are now defunct. if a method is defined, it's available. - The ``permissions`` attribute on a ``View`` is now used to provide generic permissions checking. - Use permission classes such as ``FullAnonAccess``, ``IsAuthenticated`` or ``IsUserOrIsAnonReadOnly`` to set the permissions. - -* The ``authenticators`` class becomes ``authentication``. Class names change to ``Authentication``. - -* The ``emitters`` class becomes ``renderers``. Class names change to ``Renderers``. - -* ``ResponseException`` becomes ``ErrorResponse``. - -* The mixin classes have been nicely refactored, the basic mixins are now ``RequestMixin``, ``ResponseMixin``, ``AuthMixin``, and ``ResourceMixin`` - You can reuse these mixin classes individually without using the ``View`` class. - -## 0.1.1 - -* Final build before pulling in all the refactoring changes for 0.2, in case anyone needs to hang on to 0.1. - -## 0.1.0 - -* Initial release. - -[migration]: migration.md \ No newline at end of file diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md new file mode 100644 index 00000000..a466f4b1 --- /dev/null +++ b/docs/topics/release-notes.md @@ -0,0 +1,116 @@ +# Release Notes + +> Release Early, Release Often +> +> — Eric S. Raymond, [The Cathedral and the Bazaar][cite]. + +## 2.0.0 + +* **Fix all of the things.** (Well, almost.) +* For more information please see the [2.0 migration guide][migration]. + +--- + +## 0.4.0 + +* Supports Django 1.5. +* Fixes issues with 'HEAD' method. +* Allow views to specify template used by TemplateRenderer +* More consistent error responses +* Some serializer fixes +* Fix internet explorer ajax behaviour +* Minor xml and yaml fixes +* Improve setup (eg use staticfiles, not the defunct ADMIN_MEDIA_PREFIX) +* Sensible absolute URL generation, not using hacky set_script_prefix + +## 0.3.3 + +* Added DjangoModelPermissions class to support `django.contrib.auth` style permissions. +* Use `staticfiles` for css files. + - Easier to override. Won't conflict with customised admin styles (eg grappelli) +* Templates are now nicely namespaced. + - Allows easier overriding. +* Drop implied 'pk' filter if last arg in urlconf is unnamed. + - Too magical. Explict is better than implicit. +* Saner template variable autoescaping. +* Tider setup.py +* Updated for URLObject 2.0 +* Bugfixes: + - Bug with PerUserThrottling when user contains unicode chars. + +## 0.3.2 + +* Bugfixes: + * Fix 403 for POST and PUT from the UI with UserLoggedInAuthentication (#115) + * serialize_model method in serializer.py may cause wrong value (#73) + * Fix Error when clicking OPTIONS button (#146) + * And many other fixes +* Remove short status codes + - Zen of Python: "There should be one-- and preferably only one --obvious way to do it." +* get_name, get_description become methods on the view - makes them overridable. +* Improved model mixin API - Hooks for build_query, get_instance_data, get_model, get_queryset, get_ordering + +## 0.3.1 + +* [not documented] + +## 0.3.0 + +* JSONP Support +* Bugfixes, including support for latest markdown release + +## 0.2.4 + +* Fix broken IsAdminUser permission. +* OPTIONS support. +* XMLParser. +* Drop mentions of Blog, BitBucket. + +## 0.2.3 + +* Fix some throttling bugs. +* ``X-Throttle`` header on throttling. +* Support for nesting resources on related models. + +## 0.2.2 + +* Throttling support complete. + +## 0.2.1 + +* Couple of simple bugfixes over 0.2.0 + +## 0.2.0 + +* Big refactoring changes since 0.1.0, ask on the discussion group if anything isn't clear. + The public API has been massively cleaned up. Expect it to be fairly stable from here on in. + +* ``Resource`` becomes decoupled into ``View`` and ``Resource``, your views should now inherit from ``View``, not ``Resource``. + +* The handler functions on views ``.get() .put() .post()`` etc, no longer have the ``content`` and ``auth`` args. + Use ``self.CONTENT`` inside a view to access the deserialized, validated content. + Use ``self.user`` inside a view to access the authenticated user. + +* ``allowed_methods`` and ``anon_allowed_methods`` are now defunct. if a method is defined, it's available. + The ``permissions`` attribute on a ``View`` is now used to provide generic permissions checking. + Use permission classes such as ``FullAnonAccess``, ``IsAuthenticated`` or ``IsUserOrIsAnonReadOnly`` to set the permissions. + +* The ``authenticators`` class becomes ``authentication``. Class names change to ``Authentication``. + +* The ``emitters`` class becomes ``renderers``. Class names change to ``Renderers``. + +* ``ResponseException`` becomes ``ErrorResponse``. + +* The mixin classes have been nicely refactored, the basic mixins are now ``RequestMixin``, ``ResponseMixin``, ``AuthMixin``, and ``ResourceMixin`` + You can reuse these mixin classes individually without using the ``View`` class. + +## 0.1.1 + +* Final build before pulling in all the refactoring changes for 0.2, in case anyone needs to hang on to 0.1. + +## 0.1.0 + +* Initial release. + +[cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html +[migration]: migration.md \ No newline at end of file diff --git a/docs/topics/rest-hypermedia-hateoas.md b/docs/topics/rest-hypermedia-hateoas.md index dda10eb4..8b0309b9 100644 --- a/docs/topics/rest-hypermedia-hateoas.md +++ b/docs/topics/rest-hypermedia-hateoas.md @@ -24,13 +24,13 @@ For a more thorough background, check out Klabnik's [Hypermedia API reading list REST framework is an agnositic Web API toolkit. It does help guide you towards building well-connected APIs, and makes it easy to design appropriate media types, but it does not strictly enforce any particular design style. -## What REST framework *does* provide. +## What REST framework provides. It is self evident that REST framework makes it possible to build Hypermedia APIs. The browseable API that it offers is built on HTML - the hypermedia language of the web. REST framework also includes [serialization] and [parser]/[renderer] components that make it easy to build appropriate media types, [hyperlinked relations][fields] for building well-connected systems, and great support for [content negotiation][conneg]. -## 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 [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. -- cgit v1.2.3 From cab4a2a5ad17545ac435785bf55b0b3a6c8f932c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 15:41:57 +0100 Subject: Split up doc sections more cleanly --- docs/api-guide/exceptions.md | 4 ++++ docs/api-guide/permissions.md | 5 +++++ docs/api-guide/settings.md | 4 ++++ docs/api-guide/throttling.md | 4 ++++ docs/api-guide/views.md | 4 ++-- 5 files changed, 19 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index c3bdb7b9..33cf1ca8 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -33,6 +33,10 @@ Might recieve an error response indicating that the `DELETE` method is not allow {"detail": "Method 'DELETE' not allowed."} +--- + +# API Reference + ## APIException **Signature:** `APIException(detail=None)` diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index eb290849..b25b52be 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -54,6 +54,8 @@ Or, if you're using the `@api_view` decorator with function based views. } return Response(content) +--- + # API Reference ## IsAuthenticated @@ -88,12 +90,15 @@ To use custom model permissions, override `DjangoModelPermissions` and set the ` The `DjangoModelPermissions` class also supports object-level permissions. Third-party authorization backends such as [django-guardian][guardian] that provide object-level permissions should work just fine with `DjangoModelPermissions` without any custom configuration required. +--- + # Custom permissions To implement a custom permission, override `BasePermission` and implement the `.has_permission(self, request, view, obj=None)` method. The method should return `True` if the request should be granted access, and `False` otherwise. + [cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html [authentication]: authentication.md [throttling]: throttling.md diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index f473128e..84acd797 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -30,6 +30,10 @@ you should use the `api_settings` object. For example. The `api_settings` object will check for any user-defined settings, and otherwise fallback to the default values. Any setting that uses string import paths to refer to a class will automatically import and return the referenced class, instead of the string literal. +--- + +# API Reference + ## DEFAULT_RENDERERS A list or tuple of renderer classes, that determines the default set of renderers that may be used when returning a `Response` object. diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index 3fb95ae3..22e34187 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -63,6 +63,8 @@ Or, if you're using the `@api_view` decorator with function based views. } return Response(content) +--- + # API Reference ## AnonRateThrottle @@ -144,6 +146,8 @@ For example, given the following views... User requests to either `ContactListView` or `ContactDetailView` would be restricted to a total of 1000 requests per-day. User requests to `UploadView` would be restricted to 20 requests per day. +--- + # Custom throttles To create a custom throttle, override `BaseThrottle` and implement `.allow_request(request, view)`. The method should return `True` if the request should be allowed, and `False` otherwise. diff --git a/docs/api-guide/views.md b/docs/api-guide/views.md index cbfa2e28..77349252 100644 --- a/docs/api-guide/views.md +++ b/docs/api-guide/views.md @@ -33,8 +33,8 @@ For example: """ Return a list of all users. """ - users = [user.username for user in User.objects.all()] - return Response(users) + usernames = [user.username for user in User.objects.all()] + return Response(usernames) ## API policy attributes -- cgit v1.2.3 From 6717d654d0bbfdfca4aaea84a5b4814c4e5f7567 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 21:57:23 +0100 Subject: Added @rdobson. Thanks! --- docs/topics/credits.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/credits.md b/docs/topics/credits.md index 3f4b9f0d..6df99237 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -47,6 +47,7 @@ The following people have helped make REST framework great. * Mattbo - [mattbo] * Max Hurl - [maximilianhurl] * Tomi Pajunen - [eofs] +* Rob Dobson - [rdobson] Many thanks to everyone who's contributed to the project. @@ -124,4 +125,5 @@ To contact the author directly: [j4mie]: https://github.com/j4mie [mattbo]: https://github.com/mattbo [maximilianhurl]: https://github.com/maximilianhurl -[eofs]: https://github.com/eofs \ No newline at end of file +[eofs]: https://github.com/eofs +[rdobson]: https://github.com/rdobson -- cgit v1.2.3 From 99d48f90030d174ef80498b48f56af6489865f0d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 22:07:56 +0100 Subject: Drop .parse_string_or_stream() - keep API minimal. --- docs/api-guide/parsers.md | 10 +++++----- docs/tutorial/1-serialization.md | 7 +++++-- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index 4f145ba3..a950c0e0 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -91,11 +91,11 @@ You will typically want to use both `FormParser` and `MultiPartParser` together # Custom parsers -To implement a custom parser, you should override `BaseParser`, set the `.media_type` property, and implement the `.parse_stream(self, stream, parser_context)` method. +To implement a custom parser, you should override `BaseParser`, set the `.media_type` property, and implement the `.parse(self, stream, parser_context)` method. The method should return the data that will be used to populate the `request.DATA` property. -The arguments passed to `.parse_stream()` are: +The arguments passed to `.parse()` are: ### stream @@ -116,7 +116,7 @@ The following is an example plaintext parser that will populate the `request.DAT media_type = 'text/plain' - def parse_stream(self, stream, parser_context=None): + def parse(self, stream, parser_context=None): """ Simply return a string representing the body of the request. """ @@ -124,7 +124,7 @@ The following is an example plaintext parser that will populate the `request.DAT ## Uploading file content -If your custom parser needs to support file uploads, you may return a `DataAndFiles` object from the `.parse_stream()` method. `DataAndFiles` should be instantiated with two arguments. The first argument will be used to populate the `request.DATA` property, and the second argument will be used to populate the `request.FILES` property. +If your custom parser needs to support file uploads, you may return a `DataAndFiles` object from the `.parse()` method. `DataAndFiles` should be instantiated with two arguments. The first argument will be used to populate the `request.DATA` property, and the second argument will be used to populate the `request.FILES` property. For example: @@ -133,7 +133,7 @@ For example: A naive raw file upload parser. """ - def parse_stream(self, stream, parser_context): + def parse(self, stream, parser_context): content = stream.read() name = 'example.dat' content_type = 'application/octet-stream' diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index e21433ba..5b58f293 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -134,12 +134,15 @@ We've now got a few comment instances to play with. Let's take a look at serial At this point we've translated the model instance into python native datatypes. To finalise the serialization process we render the data into `json`. - stream = JSONRenderer().render(serializer.data) - stream + content = JSONRenderer().render(serializer.data) + content # '{"id": 1, "email": "leila@example.com", "content": "nothing to say", "created": "2012-08-22T16:20:09.822"}' Deserialization is similar. First we parse a stream into python native datatypes... + import StringIO + + stream = StringIO.StringIO(content) data = JSONParser().parse(stream) ...then we restore those native datatypes into to a fully populated object instance. -- cgit v1.2.3 From 4231995fbd80e45991975ab81d9e570a9f4b72d0 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 22:19:59 +0100 Subject: parser_context includes `view`, `request`, `args`, `kwargs`. (Not `meta` and `upload_handlers`) Consistency with renderer API. --- docs/api-guide/parsers.md | 4 +++- docs/api-guide/renderers.md | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index a950c0e0..70abad9b 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -103,7 +103,9 @@ A stream-like object representing the body of the request. ### parser_context -If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content. By default it includes the keys `'upload_handlers'` and `'meta'`, which contain the values of the `request.upload_handlers` and `request.meta` properties. +Optional. If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content. + +By default this will include the following keys: `view`, `request`, `args`, `kwargs`. ## Example diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index c8addb32..24cca181 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -162,11 +162,14 @@ 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"`. +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 -- cgit v1.2.3 From fb56f215ae50da0aebe99e05036ece259fd3e6f1 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 22:39:07 +0100 Subject: Added `media_type` to `.parse()` - Consistency with renderer API. --- docs/api-guide/parsers.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index 70abad9b..18a5872c 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -101,6 +101,12 @@ The arguments passed to `.parse()` are: A stream-like object representing the body of the request. +### media_type + +Optional. If provided, this is the media type of the incoming request. + +Depending on the request's `Content-Type:` header, this may be more specific than the renderer's `media_type` attribute, and may include media type parameters. For example `"text/plain; charset=utf-8"`. + ### parser_context Optional. If supplied, this argument will be a dictionary containing any additional context that may be required to parse the request content. @@ -118,7 +124,7 @@ The following is an example plaintext parser that will populate the `request.DAT media_type = 'text/plain' - def parse(self, stream, parser_context=None): + def parse(self, stream, media_type=None, parser_context=None): """ Simply return a string representing the body of the request. """ @@ -135,7 +141,7 @@ For example: A naive raw file upload parser. """ - def parse(self, stream, parser_context): + def parse(self, stream, media_type=None, parser_context=None): content = stream.read() name = 'example.dat' content_type = 'application/octet-stream' -- cgit v1.2.3 From e126b615420fed12af58675cb4bb52e749b006bd Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 22:58:18 +0100 Subject: Negotiation API finalized. .select_renderers and .select_parsers --- docs/api-guide/content-negotiation.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/content-negotiation.md b/docs/api-guide/content-negotiation.md index ad98de3b..b95091c5 100644 --- a/docs/api-guide/content-negotiation.md +++ b/docs/api-guide/content-negotiation.md @@ -7,3 +7,9 @@ > — [RFC 2616][cite], Fielding et al. [cite]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html + +**TODO**: Describe content negotiation style used by REST framework. + +## Custom content negotiation + +It's unlikley that you'll want to provide a custom content negotiation scheme for REST framework, but you can do so if needed. To implement a custom content negotiation scheme, override `BaseContentNegotiation`, and implement the `.select_parser(request, parsers)` and `.select_renderer(request, renderers, format_suffix)` \ No newline at end of file -- cgit v1.2.3 From fed235dd0135c3eb98bb218a51f01ace5ddd3782 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 17 Oct 2012 23:09:11 +0100 Subject: Make settings consistent with corrosponding view attributes --- docs/api-guide/authentication.md | 4 ++-- docs/api-guide/parsers.md | 4 ++-- docs/api-guide/permissions.md | 4 ++-- docs/api-guide/renderers.md | 4 ++-- docs/api-guide/requests.md | 4 ++-- docs/api-guide/settings.md | 20 ++++++++++---------- docs/api-guide/throttling.md | 8 ++++---- docs/css/default.css | 4 ++++ docs/tutorial/quickstart.md | 4 ++-- 9 files changed, 30 insertions(+), 26 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 71f48163..5e5ee4ed 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -26,10 +26,10 @@ The value of `request.user` and `request.auth` for unauthenticated requests can ## Setting the authentication policy -The default authentication policy may be set globally, using the `DEFAULT_AUTHENTICATION` setting. For example. +The default authentication policy may be set globally, using the `DEFAULT_AUTHENTICATION_CLASSES` setting. For example. REST_FRAMEWORK = { - 'DEFAULT_AUTHENTICATION': ( + 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.UserBasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ) diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index 18a5872c..f7a62d3d 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -16,10 +16,10 @@ The set of valid parsers for a view is always defined as a list of classes. Whe ## Setting the parsers -The default set of parsers may be set globally, using the `DEFAULT_PARSERS` setting. For example, the following settings would allow requests with `YAML` content. +The default set of parsers may be set globally, using the `DEFAULT_PARSER_CLASSES` setting. For example, the following settings would allow requests with `YAML` content. REST_FRAMEWORK = { - 'DEFAULT_PARSERS': ( + 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.YAMLParser', ) } diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index b25b52be..249f3938 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -25,10 +25,10 @@ Object level permissions are run by REST framework's generic views when `.get_ob ## Setting the permission policy -The default permission policy may be set globally, using the `DEFAULT_PERMISSIONS` setting. For example. +The default permission policy may be set globally, using the `DEFAULT_PERMISSION_CLASSES` setting. For example. REST_FRAMEWORK = { - 'DEFAULT_PERMISSIONS': ( + 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) } diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index 24cca181..b3b8d5bc 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -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', ) diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md index 439c97bc..2770c6dd 100644 --- a/docs/api-guide/requests.md +++ b/docs/api-guide/requests.md @@ -37,7 +37,7 @@ For clarity inside your code, we recommend using `request.QUERY_PARAMS` instead ## .parsers -The `APIView` class or `@api_view` decorator will ensure that this property is automatically to a list of `Parser` instances, based on the `parser_classes` set on the view or based on the `DEFAULT_PARSERS` setting. +The `APIView` class or `@api_view` decorator will ensure that this property is automatically to a list of `Parser` instances, based on the `parser_classes` set on the view or based on the `DEFAULT_PARSER_CLASSES` setting. You won't typically need to access this property. @@ -125,4 +125,4 @@ Note that due to implementation reasons the `Request` class does not inherit fro [cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion [parsers documentation]: parsers.md [authentication documentation]: authentication.md -[browser enhancements documentation]: ../topics/browser-enhancements.md \ No newline at end of file +[browser enhancements documentation]: ../topics/browser-enhancements.md diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 84acd797..21efc853 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -11,10 +11,10 @@ Configuration for REST framework is all namespaced inside a single Django settin For example your project's `settings.py` file might include something like this: REST_FRAMEWORK = { - 'DEFAULT_RENDERERS': ( + 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.YAMLRenderer', ) - 'DEFAULT_PARSERS': ( + 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.YAMLParser', ) } @@ -26,7 +26,7 @@ you should use the `api_settings` object. For example. from rest_framework.settings import api_settings - print api_settings.DEFAULT_AUTHENTICATION + print api_settings.DEFAULT_AUTHENTICATION_CLASSES The `api_settings` object will check for any user-defined settings, and otherwise fallback to the default values. Any setting that uses string import paths to refer to a class will automatically import and return the referenced class, instead of the string literal. @@ -34,7 +34,7 @@ The `api_settings` object will check for any user-defined settings, and otherwis # API Reference -## DEFAULT_RENDERERS +## DEFAULT_RENDERER_CLASSES A list or tuple of renderer classes, that determines the default set of renderers that may be used when returning a `Response` object. @@ -46,7 +46,7 @@ Default: 'rest_framework.renderers.TemplateHTMLRenderer' ) -## DEFAULT_PARSERS +## DEFAULT_PARSER_CLASSES A list or tuple of parser classes, that determines the default set of parsers used when accessing the `request.DATA` property. @@ -57,7 +57,7 @@ Default: 'rest_framework.parsers.FormParser' ) -## DEFAULT_AUTHENTICATION +## DEFAULT_AUTHENTICATION_CLASSES A list or tuple of authentication classes, that determines the default set of authenticators used when accessing the `request.user` or `request.auth` properties. @@ -68,25 +68,25 @@ Default: 'rest_framework.authentication.UserBasicAuthentication' ) -## DEFAULT_PERMISSIONS +## DEFAULT_PERMISSION_CLASSES A list or tuple of permission classes, that determines the default set of permissions checked at the start of a view. Default: `()` -## DEFAULT_THROTTLES +## DEFAULT_THROTTLE_CLASSES A list or tuple of throttle classes, that determines the default set of throttles checked at the start of a view. Default: `()` -## DEFAULT_MODEL_SERIALIZER +## DEFAULT_MODEL_SERIALIZER_CLASS **TODO** Default: `rest_framework.serializers.ModelSerializer` -## DEFAULT_PAGINATION_SERIALIZER +## DEFAULT_PAGINATION_SERIALIZER_CLASS **TODO** diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index 22e34187..435b20ce 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -27,10 +27,10 @@ If any throttle check fails an `exceptions.Throttled` exception will be raised, ## Setting the throttling policy -The default throttling policy may be set globally, using the `DEFAULT_THROTTLES` and `DEFAULT_THROTTLE_RATES` settings. For example. +The default throttling policy may be set globally, using the `DEFAULT_THROTTLE_CLASSES` and `DEFAULT_THROTTLE_RATES` settings. For example. REST_FRAMEWORK = { - 'DEFAULT_THROTTLES': ( + 'DEFAULT_THROTTLE_CLASSES': ( 'rest_framework.throttles.AnonThrottle', 'rest_framework.throttles.UserThrottle', ) @@ -100,7 +100,7 @@ For example, multiple user throttle rates could be implemented by using the foll ...and the following settings. REST_FRAMEWORK = { - 'DEFAULT_THROTTLES': ( + 'DEFAULT_THROTTLE_CLASSES': ( 'example.throttles.BurstRateThrottle', 'example.throttles.SustainedRateThrottle', ) @@ -135,7 +135,7 @@ For example, given the following views... ...and the following settings. REST_FRAMEWORK = { - 'DEFAULT_THROTTLES': ( + 'DEFAULT_THROTTLE_CLASSES': ( 'rest_framework.throttles.ScopedRateThrottle', ) 'DEFAULT_THROTTLE_RATES': { diff --git a/docs/css/default.css b/docs/css/default.css index c1d2e885..57446ff9 100644 --- a/docs/css/default.css +++ b/docs/css/default.css @@ -88,6 +88,10 @@ pre { font-weight: bold; } +.nav-list a { + overflow: hidden; +} + /* Set the table of contents to static so it flows back into the content when viewed on tablets and smaller. */ @media (max-width: 767px) { diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 851db3c7..6bde725b 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -126,7 +126,7 @@ We'd also like to set a few global settings. We'd like to turn on pagination, a ) REST_FRAMEWORK = { - 'DEFAULT_PERMISSIONS': ('rest_framework.permissions.IsAdminUser',), + 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',), 'PAGINATE_BY': 10 } @@ -169,4 +169,4 @@ If you want to get a more in depth understanding of how REST framework fits toge [image]: ../img/quickstart.png [tutorial]: 1-serialization.md -[guide]: ../#api-guide \ No newline at end of file +[guide]: ../#api-guide -- cgit v1.2.3 From e8f542aac88677cd95c473d56511cadbc0c67813 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 18 Oct 2012 09:19:38 +0100 Subject: Minor docs fix --- docs/api-guide/parsers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index 18a5872c..0985b2ca 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -91,7 +91,7 @@ You will typically want to use both `FormParser` and `MultiPartParser` together # Custom parsers -To implement a custom parser, you should override `BaseParser`, set the `.media_type` property, and implement the `.parse(self, stream, parser_context)` method. +To implement a custom parser, you should override `BaseParser`, set the `.media_type` property, and implement the `.parse(self, stream, media_type, parser_context)` method. The method should return the data that will be used to populate the `request.DATA` property. @@ -103,7 +103,7 @@ A stream-like object representing the body of the request. ### media_type -Optional. If provided, this is the media type of the incoming request. +Optional. If provided, this is the media type of the incoming request content. Depending on the request's `Content-Type:` header, this may be more specific than the renderer's `media_type` attribute, and may include media type parameters. For example `"text/plain; charset=utf-8"`. -- cgit v1.2.3 From efabd2bb1b762fbdee2b48fa3a6ccb8f23c7e8dc Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 19 Oct 2012 19:59:46 +0100 Subject: docs, docs, docs, docs, docs, docs, docs --- docs/api-guide/content-negotiation.md | 57 +++++++++++++++++++++++++++++++++-- docs/api-guide/format-suffixes.md | 52 +++++++++++++++++++++++++++++++- docs/api-guide/pagination.md | 6 +++- 3 files changed, 110 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/content-negotiation.md b/docs/api-guide/content-negotiation.md index b95091c5..78dc0747 100644 --- a/docs/api-guide/content-negotiation.md +++ b/docs/api-guide/content-negotiation.md @@ -8,8 +8,59 @@ [cite]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html -**TODO**: Describe content negotiation style used by REST framework. +Content negotiation is the process of selecting one of multiple possible representations to return to a client, based on client or server preferences. -## Custom content negotiation +## Determining the accepted renderer -It's unlikley that you'll want to provide a custom content negotiation scheme for REST framework, but you can do so if needed. To implement a custom content negotiation scheme, override `BaseContentNegotiation`, and implement the `.select_parser(request, parsers)` and `.select_renderer(request, renderers, format_suffix)` \ No newline at end of file +REST framework uses a simple style of content negotition to determine which media type should be returned to a client, based on the available renderers, the priorities of each of those renderers, and the client's `Accept:` header. The style used is partly client-driven, and partly server-driven. + +1. More specific media types are given preference to less specific media types. +2. If multiple media types have the same specificity, then preference is given to based on the ordering of the renderers configured for the given view. + +For example, given the following `Accept` header: + + application/json; indent=4, application/json, application/yaml, text/html, */* + +The priorities for each of the given media types would be: + +* `application/json; indent=4` +* `application/json`, `application/yaml` and `text/html` +* `*/*` + +If the requested view was only configured with renderers for `YAML` and `HTML`, then REST framework would select whichever renderer was listed first in the `renderer_classes` list or `DEFAULT_RENDERER_CLASSES` setting. + +For more information on the `HTTP Accept` header, see [RFC 2616][accept-header] + +--- + +**Note**: "q" values are not taken into account by REST framework when determining preference. The use of "q" values negatively impacts caching, and in the author's opinion they are an unnecessary and overcomplicated approach to content negotiation. + +This is a valid approach as the HTTP spec deliberately underspecifies how a server should weight server-based preferences against client-based preferences. + +--- + +# Custom content negotiation + +It's unlikley that you'll want to provide a custom content negotiation scheme for REST framework, but you can do so if needed. To implement a custom content negotiation scheme override `BaseContentNegotiation`. + +REST framework's content negotiation classes handle selection of both the approprate parser for the requesr, and the appropriate renderer for the response, so you should implement both the `.select_parser(request, parsers)` and `.select_renderer(request, renderers, format_suffix)` methods. + +## Example + +The following is a custom content negotiation class which ignores the client +request when selecting the appropriate parser or renderer. + + class IgnoreClientContentNegotiation(BaseContentNegotiation): + def select_parser(self, request, parsers): + """ + Select the first parser in the `.parser_classes` list. + """ + return parsers[0] + + def select_renderer(self, request, renderers, format_suffix): + """ + Select the first renderer in the `.renderer_classes` list. + """ + return renderers[0] + +[accept-header]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html \ No newline at end of file diff --git a/docs/api-guide/format-suffixes.md b/docs/api-guide/format-suffixes.md index 7d72d9f8..6d5feba4 100644 --- a/docs/api-guide/format-suffixes.md +++ b/docs/api-guide/format-suffixes.md @@ -7,5 +7,55 @@ used all the time. > > — Roy Fielding, [REST discuss mailing list][cite] -[cite]: http://tech.groups.yahoo.com/group/rest-discuss/message/5857 +A common pattern for Web APIs is to use filename extensions on URLs to provide an endpoint for a given media type. For example, 'http://example.com/api/users.json' to serve a JSON representation. + +Adding format-suffix patterns to each individual entry in the URLconf for your API is error-prone and non-DRY, so REST framework provides a shortcut to adding these patterns to your URLConf. + +## format_suffix_patterns + +**Signature**: format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None) + +Returns a URL pattern list which includes format suffix patterns appended to each of the URL patterns provided. + +Arguments: + +* **urlpatterns**: Required. A URL pattern list. +* **suffix_required**: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to `False`, meaning that suffixes are optional by default. +* **allowed**: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used. + +Example: + + from rest_framework.urlpatterns import format_suffix_patterns + + urlpatterns = patterns('blog.views', + url(r'^/$', 'api_root'), + url(r'^comment/$', 'comment_root'), + url(r'^comment/(?P