From 2a0d9b2e3c6d3d66151dc380021a9c043d85b1fc Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 19 Oct 2012 20:00:35 +0100 Subject: [PATCH] Latest docs build --- api-guide/authentication.html | 4 +-- api-guide/content-negotiation.html | 44 ++++++++++++++++++++++++++++++ api-guide/exceptions.html | 3 ++ api-guide/format-suffixes.html | 38 ++++++++++++++++++++++++++ api-guide/pagination.html | 7 +++-- api-guide/parsers.html | 20 ++++++++------ api-guide/permissions.html | 6 ++-- api-guide/renderers.html | 11 ++++---- api-guide/requests.html | 2 +- api-guide/settings.html | 37 +++++++++++++------------ api-guide/throttling.html | 10 ++++--- api-guide/views.html | 4 +-- css/default.css | 4 +++ topics/credits.html | 1 + tutorial/1-serialization.html | 9 ++++-- tutorial/quickstart.html | 2 +- 16 files changed, 155 insertions(+), 47 deletions(-) diff --git a/api-guide/authentication.html b/api-guide/authentication.html index b7ee8c155..968051f66 100644 --- a/api-guide/authentication.html +++ b/api-guide/authentication.html @@ -143,9 +143,9 @@

If no class authenticates, request.user will be set to an instance of django.contrib.auth.models.AnonymousUser, and request.auth will be set to None.

The value of request.user and request.auth for unauthenticated requests can be modified using the UNAUTHENTICATED_USER and UNAUTHENTICATED_TOKEN settings.

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/api-guide/content-negotiation.html b/api-guide/content-negotiation.html
index e0edb464b..1e3a7e462 100644
--- a/api-guide/content-negotiation.html
+++ b/api-guide/content-negotiation.html
@@ -113,6 +113,9 @@
             
@@ -125,6 +128,47 @@
 

HTTP has provisions for several mechanisms for "content negotiation" - the process of selecting the best representation for a given response when there are multiple representations available.

RFC 2616, Fielding et al.

+

Content negotiation is the process of selecting one of multiple possible representations to return to a client, based on client or server preferences.

+

Determining the accepted renderer

+

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. +
  3. 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.
  4. +
+

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

+
+

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]
+
diff --git a/api-guide/exceptions.html b/api-guide/exceptions.html index 22c80c115..6634ae52d 100644 --- a/api-guide/exceptions.html +++ b/api-guide/exceptions.html @@ -114,6 +114,7 @@
+
+

API Reference

APIException

Signature: APIException(detail=None)

The base class for all exceptions raised inside REST framework.

diff --git a/api-guide/format-suffixes.html b/api-guide/format-suffixes.html index 26baf81af..303889055 100644 --- a/api-guide/format-suffixes.html +++ b/api-guide/format-suffixes.html @@ -113,6 +113,8 @@
@@ -126,6 +128,42 @@ used all the time.

— Roy Fielding, REST discuss mailing list

+

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:

+ +

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<pk>[0-9]+)/$', 'comment_instance')
+)
+
+urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
+
+

When using format_suffix_patterns, you must make sure to add the 'format' keyword argument to the corresponding views. For example.

+
@api_view(('GET',))
+def api_root(request, format=None):
+    # do stuff...
+
+

The name of the kwarg used may be modified by using the FORMAT_SUFFIX_KWARG setting.

+

Also note that format_suffix_patterns does not support descending into include URL patterns.

+
+

Accept headers vs. format suffixes

+

There seems to be a view among some of the Web community that filename extensions are not a RESTful pattern, and that HTTP Accept headers should always be used instead.
+

+

It is actually a misconception. For example, take the following quote from Roy Fielding discussing the relative merits of query parameter media-type indicators vs. file extension media-type indicators:

+

“That's why I always prefer extensions. Neither choice has anything to do with REST.” — Roy Fielding, REST discuss mailing list

+

The quote does not mention Accept headers, but it does make it clear that format suffixes should be considered an acceptable pattern.

diff --git a/api-guide/pagination.html b/api-guide/pagination.html index bf5497392..3fa1ae502 100644 --- a/api-guide/pagination.html +++ b/api-guide/pagination.html @@ -116,7 +116,8 @@
  • Paginating basic data
  • Paginating QuerySets
  • Pagination in the generic views
  • -
  • Custom pagination serializers
  • +
  • Custom pagination serializers
  • +
  • Example
  • @@ -208,9 +209,11 @@ def user_list(request): paginate_by = 10

    For more complex requirements such as serialization that differs depending on the requested media type you can override the .get_paginate_by() and .get_pagination_serializer_class() methods.

    -

    Custom pagination serializers

    +
    +

    Custom pagination serializers

    To create a custom pagination serializer class you should override pagination.BasePaginationSerializer and set the fields that you want the serializer to return.

    You can also override the name used for the object list field, by setting the results_field attribute, which defaults to 'results'.

    +

    Example

    For example, to nest a pair of links labelled 'prev' and 'next', and set the name for the results field to 'objects', you might use something like this.

    class LinksSerializer(serializers.Serializer):
         next = pagination.NextURLField(source='*')
    diff --git a/api-guide/parsers.html b/api-guide/parsers.html
    index da2aaada8..7989de98d 100644
    --- a/api-guide/parsers.html
    +++ b/api-guide/parsers.html
    @@ -142,9 +142,9 @@ sending more complex data than simple forms

    How the parser is determined

    The set of valid parsers for a view is always defined as a list of classes. When either request.DATA or request.FILES is accessed, REST framework will examine the Content-Type header on the incoming request, and determine which parser to use to parse the request content.

    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',
         )
     }
    @@ -191,13 +191,17 @@ def example_view(request, format=None):
     

    .media_type: multipart/form-data


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

    A stream-like object representing the body of the request.

    +

    media_type

    +

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

    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

    The following is an example plaintext parser that will populate the request.DATA property with a string representing the body of the request.

    class PlainTextParser(BaseParser):
    @@ -207,21 +211,21 @@ Plain text parser.
     
     media_type = 'text/plain'
     
    -def parse_stream(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.
         """
         return stream.read()
     

    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:

    class SimpleFileUploadParser(BaseParser):
         """
         A naive raw file upload parser.
         """
     
    -    def parse_stream(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'
    diff --git a/api-guide/permissions.html b/api-guide/permissions.html
    index c34933064..42aa10c47 100644
    --- a/api-guide/permissions.html
    +++ b/api-guide/permissions.html
    @@ -145,9 +145,9 @@ If any permission check fails an exceptions.PermissionDenied except
     

    REST framework permissions also support object-level permissioning. Object level permissions are used to determine if a user should be allowed to act on a particular object, which will typically be a model instance.

    Object level permissions are run by REST framework's generic views when .get_object() is called. As with view level permissions, an exceptions.PermissionDenied exception will be raised if the user is not allowed to act on the given object.

    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',
         )
     }
    @@ -171,6 +171,7 @@ def example_view(request, format=None):
         }
         return Response(content)
     
    +

    API Reference

    IsAuthenticated

    The IsAuthenticated permission class will deny permission to any unauthenticated user, and allow permission otherwise.

    @@ -191,6 +192,7 @@ def example_view(request, format=None):

    The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a view model permission for GET requests.

    To use custom model permissions, override DjangoModelPermissions and set the .perms_map property. Refer to the source code for details.

    The DjangoModelPermissions class also supports object-level permissions. Third-party authorization backends such as django-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.

    diff --git a/api-guide/renderers.html b/api-guide/renderers.html index 2e9fb4b21..6104d0e8d 100644 --- a/api-guide/renderers.html +++ b/api-guide/renderers.html @@ -146,9 +146,9 @@

    The basic process of content negotiation involves examining the request's Accept header, to determine which media types it expects in the response. Optionally, format suffixes on the URL may be used to explicitly request a particular representation. For example the URL http://example.com/api/users_count.json might be an endpoint that always returns JSON data.

    For more information see the documentation on content negotation.

    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',
         )
    @@ -241,10 +241,11 @@ Unlike other renderers, the data passed to the Response does not ne
     

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

    +

    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.

    +

    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
    diff --git a/api-guide/requests.html b/api-guide/requests.html
    index 40b84f489..997879e6e 100644
    --- a/api-guide/requests.html
    +++ b/api-guide/requests.html
    @@ -157,7 +157,7 @@
     

    request.QUERY_PARAMS is a more correcly named synonym for request.GET.

    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.

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


    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.

    diff --git a/api-guide/settings.html b/api-guide/settings.html index a7a9b52ad..cd4a93271 100644 --- a/api-guide/settings.html +++ b/api-guide/settings.html @@ -114,13 +114,14 @@

    API policy attributes

    The following attributes control the pluggable aspects of API views.

    diff --git a/css/default.css b/css/default.css index c1d2e885d..57446ff98 100644 --- a/css/default.css +++ b/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/topics/credits.html b/topics/credits.html index e6c76142b..d67c97d02 100644 --- a/topics/credits.html +++ b/topics/credits.html @@ -169,6 +169,7 @@
  • Mattbo - mattbo
  • Max Hurl - maximilianhurl
  • Tomi Pajunen - eofs
  • +
  • Rob Dobson - rdobson
  • Many thanks to everyone who's contributed to the project.

    Additional thanks

    diff --git a/tutorial/1-serialization.html b/tutorial/1-serialization.html index e009796b4..509384f63 100644 --- a/tutorial/1-serialization.html +++ b/tutorial/1-serialization.html @@ -238,12 +238,15 @@ serializer.data # {'id': 1, 'email': u'leila@example.com', 'content': u'nothing to say', 'created': datetime.datetime(2012, 8, 22, 16, 20, 9, 822774, tzinfo=<UTC>)}

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

    -
    data = JSONParser().parse(stream)
    +
    import StringIO
    +
    +stream = StringIO.StringIO(content)
    +data = JSONParser().parse(stream)
     

    ...then we restore those native datatypes into to a fully populated object instance.

    serializer = CommentSerializer(data)
    diff --git a/tutorial/quickstart.html b/tutorial/quickstart.html
    index f24b1e76f..3841b93ee 100644
    --- a/tutorial/quickstart.html
    +++ b/tutorial/quickstart.html
    @@ -225,7 +225,7 @@ urlpatterns += patterns('',
     )
     
     REST_FRAMEWORK = {
    -    'DEFAULT_PERMISSIONS': ('rest_framework.permissions.IsAdminUser',),
    +    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
         'PAGINATE_BY': 10
     }