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.
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.
+
+- More specific media types are given preference to less specific media types.
+- 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
+
+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 @@
+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 @@— 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.
+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:
+False
, meaning that suffixes are optional by default.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.
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 @@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.
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'
.
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 @@
REST_FRAMEWORK = {
- 'DEFAULT_RENDERERS': (
+ 'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.YAMLRenderer',
)
- 'DEFAULT_PARSERS': (
+ 'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.YAMLParser',
)
}
@@ -157,10 +158,12 @@
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.
-DEFAULT_RENDERERS
+
+API Reference
+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.
Default:
(
@@ -169,7 +172,7 @@ print api_settings.DEFAULT_AUTHENTICATION
'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.
Default:
(
@@ -177,7 +180,7 @@ print api_settings.DEFAULT_AUTHENTICATION
'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.
Default:
(
@@ -185,16 +188,16 @@ print api_settings.DEFAULT_AUTHENTICATION
'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
Default: rest_framework.pagination.PaginationSerializer
FORMAT_SUFFIX_KWARG
diff --git a/api-guide/throttling.html b/api-guide/throttling.html
index bfef75b98..b8837c5ac 100644
--- a/api-guide/throttling.html
+++ b/api-guide/throttling.html
@@ -142,9 +142,9 @@
Before running the main body of the view each throttle in the list is checked.
If any throttle check fails an exceptions.Throttled
exception will be raised, and the main body of the view will not run.
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',
)
@@ -174,6 +174,7 @@ def example_view(request, format=None):
}
return Response(content)
+
API Reference
AnonRateThrottle
The AnonThrottle
will only ever throttle unauthenticated users. The IP address of the incoming request is used to generate a unique key to throttle against.
@@ -200,7 +201,7 @@ class SustainedRateThrottle(UserRateThrottle):
...and the following settings.
REST_FRAMEWORK = {
- 'DEFAULT_THROTTLES': (
+ 'DEFAULT_THROTTLE_CLASSES': (
'example.throttles.BurstRateThrottle',
'example.throttles.SustainedRateThrottle',
)
@@ -229,7 +230,7 @@ class UploadView(APIView):
...and the following settings.
REST_FRAMEWORK = {
- 'DEFAULT_THROTTLES': (
+ 'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttles.ScopedRateThrottle',
)
'DEFAULT_THROTTLE_RATES': {
@@ -239,6 +240,7 @@ class UploadView(APIView):
}
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.
Optionally you may also override the .wait()
method. If implemented, .wait()
should return a recomended number of seconds to wait before attempting the next request, or None
. The .wait()
method will only be called if .allow_request()
has previously returned False
.
diff --git a/api-guide/views.html b/api-guide/views.html
index ea7add8ab..4350eb1ab 100644
--- a/api-guide/views.html
+++ b/api-guide/views.html
@@ -154,8 +154,8 @@
"""
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
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
}