diff --git a/api-guide/authentication.html b/api-guide/authentication.html index bbce28355..9b11fbe5b 100644 --- a/api-guide/authentication.html +++ b/api-guide/authentication.html @@ -307,7 +307,9 @@ WSGIPassAuthorization On 'rest_framework.authtoken' ) -
Make sure to run manage.py syncdb
after changing your settings. The authtoken
database tables are managed by south (see Schema migrations below).
Note: Make sure to run manage.py syncdb
after changing your settings. The rest_framework.authtoken
app provides both Django (from v1.7) and South database migrations. See Schema migrations below.
You'll also need to create tokens for your users.
from rest_framework.authtoken.models import Token
@@ -362,7 +364,10 @@ for user in User.objects.all():
Note that the default obtain_auth_token
view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the obtain_auth_token
view, you can do so by overriding the ObtainAuthToken
view class, and using that in your url conf instead.
The rest_framework.authtoken
app includes a south migration that will create the authtoken table.
The rest_framework.authtoken
app includes both Django native migrations (for Django versions >1.7) and South migrations (for Django versions <1.7) that will create the authtoken table.
Note: From REST Framework v2.4.0 using South with Django <1.7 requires upgrading South v1.0+
+If you're using a custom user model you'll need to make sure that any initial migration that creates the user table runs before the authtoken table is created.
You can do so by inserting a needed_by
attribute in your user migration:
class Migration:
diff --git a/api-guide/fields.html b/api-guide/fields.html
index 72ef27e40..4ca9b1fb8 100644
--- a/api-guide/fields.html
+++ b/api-guide/fields.html
@@ -213,6 +213,7 @@ a.fusion-poweredby {
DRF Compound Fields
DRF Extra Fields
django-rest-framework-gis
+django-rest-framework-hstore
@@ -329,10 +330,11 @@ class UserSerializer(serializers.ModelSerializer):
A Boolean representation.
Corresponds to django.db.models.fields.BooleanField
.
CharField
-A text representation, optionally validates the text to be shorter than max_length
and longer than min_length
.
+A text representation, optionally validates the text to be shorter than max_length
and longer than min_length
.
+If allow_none
is False
(default), None
values will be converted to an empty string.
Corresponds to django.db.models.fields.CharField
or django.db.models.fields.TextField
.
-Signature: CharField(max_length=None, min_length=None)
+Signature: CharField(max_length=None, min_length=None, allow_none=False)
URLField
Corresponds to django.db.models.fields.URLField
. Uses Django's django.core.validators.URLValidator
for validation.
Signature: URLField(max_length=200, min_length=None)
@@ -461,6 +463,8 @@ class ColourField(serializers.WritableField):
The drf-extra-fields package provides extra serializer fields for REST framework, including Base64ImageField
and PointField
classes.
django-rest-framework-gis
The django-rest-framework-gis package provides geographic addons for django rest framework like a GeometryField
field and a GeoJSON serializer.
+django-rest-framework-hstore
+The django-rest-framework-hstore package provides an HStoreField
to support django-hstore DictionaryField
model field.
diff --git a/api-guide/generic-views.html b/api-guide/generic-views.html
index a9f96812c..be6e19f1a 100644
--- a/api-guide/generic-views.html
+++ b/api-guide/generic-views.html
@@ -262,7 +262,7 @@ class UserList(generics.ListCreateAPIView):
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
-For very simple cases you might want to pass through any class attributes using the .as_view()
method. For example, your URLconf might include something the following entry.
For very simple cases you might want to pass through any class attributes using the .as_view()
method. For example, your URLconf might include something like the following entry:
url(r'^/users/', ListCreateAPIView.as_view(model=User), name='user-list')
get_queryset(self)
Returns the queryset that should be used for list views, and that should be used as the base for lookups in detail views. Defaults to returning the queryset specified by the queryset
attribute, or the default queryset for the model if the model
shortcut is being used.
This method should always be used rather than accessing self.queryset
directly, as self.queryset
gets evaluated only once, and those results are cached for all subsequent requests.
May be overridden to provide dynamic behavior such as returning a queryset that is specific to the user making the request.
+May be overridden to provide dynamic behavior, such as returning a queryset, that is specific to the user making the request.
For example:
def get_queryset(self):
user = self.request.user
@@ -308,7 +308,7 @@ class UserList(generics.ListCreateAPIView):
get_object(self)
Returns an object instance that should be used for detail views. Defaults to using the lookup_field
parameter to filter the base queryset.
May be overridden to provide more complex behavior such as object lookups based on more than one URL kwarg.
+May be overridden to provide more complex behavior, such as object lookups based on more than one URL kwarg.
For example:
def get_object(self):
queryset = self.get_queryset()
@@ -323,7 +323,7 @@ class UserList(generics.ListCreateAPIView):
Note that if your API doesn't include any object level permissions, you may optionally exclude the self.check_object_permissions
, and simply return the object from the get_object_or_404
lookup.
get_filter_backends(self)
Returns the classes that should be used to filter the queryset. Defaults to returning the filter_backends
attribute.
-May be override to provide more complex behavior with filters, as using different (or even exlusive) lists of filter_backends depending on different criteria.
+May be overridden to provide more complex behavior with filters, such as using different (or even exlusive) lists of filter_backends depending on different criteria.
For example:
def get_filter_backends(self):
if "geo_route" in self.request.QUERY_PARAMS:
@@ -335,7 +335,7 @@ class UserList(generics.ListCreateAPIView):
get_serializer_class(self)
Returns the class that should be used for the serializer. Defaults to returning the serializer_class
attribute, or dynamically generating a serializer class if the model
shortcut is being used.
-May be override to provide dynamic behavior such as using different serializers for read and write operations, or providing different serializers to different types of users.
+May be overridden to provide dynamic behavior, such as using different serializers for read and write operations, or providing different serializers to different types of users.
For example:
def get_serializer_class(self):
if self.request.user.is_staff:
@@ -344,7 +344,7 @@ class UserList(generics.ListCreateAPIView):
get_paginate_by(self)
Returns the page size to use with pagination. By default this uses the paginate_by
attribute, and may be overridden by the client if the paginate_by_param
attribute is set.
-You may want to override this method to provide more complex behavior such as modifying page sizes based on the media type of the response.
+You may want to override this method to provide more complex behavior, such as modifying page sizes based on the media type of the response.
For example:
def get_paginate_by(self):
if self.request.accepted_renderer.format == 'html':
@@ -378,7 +378,7 @@ class UserList(generics.ListCreateAPIView):
Mixins
-The mixin classes provide the actions that are used to provide the basic view behavior. Note that the mixin classes provide action methods rather than defining the handler methods such as .get()
and .post()
directly. This allows for more flexible composition of behavior.
+The mixin classes provide the actions that are used to provide the basic view behavior. Note that the mixin classes provide action methods rather than defining the handler methods, such as .get()
and .post()
, directly. This allows for more flexible composition of behavior.
ListModelMixin
Provides a .list(request, *args, **kwargs)
method, that implements listing a queryset.
If the queryset is populated, this returns a 200 OK
response, with a serialized representation of the queryset as the body of the response. The response data may optionally be paginated.
diff --git a/api-guide/routers.html b/api-guide/routers.html
index 70dd61c49..77c6e5850 100644
--- a/api-guide/routers.html
+++ b/api-guide/routers.html
@@ -190,6 +190,7 @@ a.fusion-poweredby {
SimpleRouter
DefaultRouter
Custom Routers
+Customizing dynamic routes
Example
Advanced custom routers
Third Party Packages
@@ -247,32 +248,36 @@ urlpatterns = router.urls
This means you'll need to explicitly set the base_name
argument when registering the viewset, as it could not be automatically determined from the model name.
Extra link and actions
-Any methods on the viewset decorated with @link
or @action
will also be routed.
+
Any methods on the viewset decorated with @detail_route
or @list_route
will also be routed.
For example, given a method like this on the UserViewSet
class:
from myapp.permissions import IsAdminOrIsSelf
-from rest_framework.decorators import action
+from rest_framework.decorators import detail_route
-@action(permission_classes=[IsAdminOrIsSelf])
-def set_password(self, request, pk=None):
+class UserViewSet(ModelViewSet):
...
+
+ @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
+ def set_password(self, request, pk=None):
+ ...
The following URL pattern would additionally be generated:
- URL pattern:
^users/{pk}/set_password/$
Name: 'user-set-password'
+For more information see the viewset documentation on marking extra actions for routing.
API Guide
SimpleRouter
-This router includes routes for the standard set of list
, create
, retrieve
, update
, partial_update
and destroy
actions. The viewset can also mark additional methods to be routed, using the @link
or @action
decorators.
+This router includes routes for the standard set of list
, create
, retrieve
, update
, partial_update
and destroy
actions. The viewset can also mark additional methods to be routed, using the @detail_route
or @list_route
decorators.
URL Style HTTP Method Action URL Name
{prefix}/ GET list {basename}-list
POST create
+ {prefix}/{methodname}/ GET, or as specified by `methods` argument `@list_route` decorated method {basename}-{methodname}
{prefix}/{lookup}/ GET retrieve {basename}-detail
PUT update
PATCH partial_update
DELETE destroy
- {prefix}/{lookup}/{methodname}/ GET @link decorated method {basename}-{methodname}
- POST @action decorated method
+ {prefix}/{lookup}/{methodname}/ GET, or as specified by `methods` argument `@detail_route` decorated method {basename}-{methodname}
By default the URLs created by SimpleRouter
are appended with a trailing slash.
@@ -280,6 +285,11 @@ This behavior can be modified by setting the trailing_slash
argumen
router = SimpleRouter(trailing_slash=False)
Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.
+The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the lookup_value_regex
attribute on the viewset. For example, you can limit the lookup to valid UUIDs:
+class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
+ lookup_field = 'my_model_id'
+ lookup_value_regex = '[0-9a-f]{32}'
+
DefaultRouter
This router is similar to SimpleRouter
as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional .json
style format suffixes.
@@ -287,12 +297,12 @@ This behavior can be modified by setting the trailing_slash
argumen
[.format] GET automatically generated root view api-root
{prefix}/[.format] GET list {basename}-list
POST create
+ {prefix}/{methodname}/[.format] GET, or as specified by `methods` argument `@list_route` decorated method {basename}-{methodname}
{prefix}/{lookup}/[.format] GET retrieve {basename}-detail
PUT update
PATCH partial_update
DELETE destroy
- {prefix}/{lookup}/{methodname}/[.format] GET @link decorated method {basename}-{methodname}
- POST @action decorated method
+ {prefix}/{lookup}/{methodname}/[.format] GET, or as specified by `methods` argument `@detail_route` decorated method {basename}-{methodname}
As with SimpleRouter
the trailing slashes on the URL routes can be removed by setting the trailing_slash
argument to False
when instantiating the router.
@@ -314,26 +324,75 @@ This behavior can be modified by setting the trailing_slash
argumen
{basename}
- The base to use for the URL names that are created.
initkwargs: A dictionary of any additional arguments that should be passed when instantiating the view. Note that the suffix
argument is reserved for identifying the viewset type, used when generating the view name and breadcrumb links.
+Customizing dynamic routes
+You can also customize how the @list_route
and @detail_route
decorators are routed.
+To route either or both of these decorators, include a DynamicListRoute
and/or DynamicDetailRoute
named tuple in the .routes
list.
+The arguments to DynamicListRoute
and DynamicDetailRoute
are:
+url: A string representing the URL to be routed. May include the same format strings as Route
, and additionally accepts the {methodname}
and {methodnamehyphen}
format strings.
+name: The name of the URL as used in reverse
calls. May include the following format strings: {basename}
, {methodname}
and {methodnamehyphen}
.
+initkwargs: A dictionary of any additional arguments that should be passed when instantiating the view.
Example
The following example will only route to the list
and retrieve
actions, and does not use the trailing slash convention.
-from rest_framework.routers import Route, SimpleRouter
+from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter
-class ReadOnlyRouter(SimpleRouter):
+class CustomReadOnlyRouter(SimpleRouter):
"""
A router for read-only APIs, which doesn't use trailing slashes.
"""
routes = [
- Route(url=r'^{prefix}$',
- mapping={'get': 'list'},
- name='{basename}-list',
- initkwargs={'suffix': 'List'}),
- Route(url=r'^{prefix}/{lookup}$',
- mapping={'get': 'retrieve'},
- name='{basename}-detail',
- initkwargs={'suffix': 'Detail'})
+ Route(
+ url=r'^{prefix}$',
+ mapping={'get': 'list'},
+ name='{basename}-list',
+ initkwargs={'suffix': 'List'}
+ ),
+ Route(
+ url=r'^{prefix}/{lookup}$',
+ mapping={'get': 'retrieve'},
+ name='{basename}-detail',
+ initkwargs={'suffix': 'Detail'}
+ ),
+ DynamicDetailRoute(
+ url=r'^{prefix}/{lookup}/{methodnamehyphen}$',
+ name='{basename}-{methodnamehyphen}',
+ initkwargs={}
+ )
]
-The SimpleRouter
class provides another example of setting the .routes
attribute.
+Let's take a look at the routes our CustomReadOnlyRouter
would generate for a simple viewset.
+views.py
:
+class UserViewSet(viewsets.ReadOnlyModelViewSet):
+ """
+ A viewset that provides the standard actions
+ """
+ queryset = User.objects.all()
+ serializer_class = UserSerializer
+ lookup_field = 'username'
+
+ @detail_route()
+ def group_names(self, request):
+ """
+ Returns a list of all the group names that the given
+ user belongs to.
+ """
+ user = self.get_object()
+ groups = user.groups.all()
+ return Response([group.name for group in groups])
+
+urls.py
:
+router = CustomReadOnlyRouter()
+router.register('users', UserViewSet)
+urlpatterns = router.urls
+
+The following mappings would be generated...
+
+ URL HTTP Method Action URL Name
+ /users GET list user-list
+ /users/{username} GET retrieve user-detail
+ /users/{username}/group-names GET group_names user-group-names
+
+
+For another example of setting the .routes
attribute, see the source code for the SimpleRouter
class.
Advanced custom routers
If you want to provide totally custom behavior, you can override BaseRouter
and override the get_urls(self)
method. The method should inspect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the self.registry
attribute.
You may also want to override the get_default_base_name(self, viewset)
method, or else always explicitly set the base_name
argument when registering your viewsets with the router.
diff --git a/api-guide/serializers.html b/api-guide/serializers.html
index 850b6dc59..f90aff167 100644
--- a/api-guide/serializers.html
+++ b/api-guide/serializers.html
@@ -209,6 +209,7 @@ a.fusion-poweredby {
Third party packages
MongoengineModelSerializer
GeoFeatureModelSerializer
+HStoreSerializer
@@ -672,6 +673,8 @@ The ModelSerializer
class lets you automatically create a Serialize
The django-rest-framework-mongoengine package provides a MongoEngineModelSerializer
serializer class that supports using MongoDB as the storage layer for Django REST framework.
GeoFeatureModelSerializer
The django-rest-framework-gis package provides a GeoFeatureModelSerializer
serializer class that supports GeoJSON both for read and write operations.
+HStoreSerializer
+The django-rest-framework-hstore package provides an HStoreSerializer
to support django-hstore DictionaryField
model field and its schema-mode
feature.
diff --git a/api-guide/settings.html b/api-guide/settings.html
index 880b3249d..598232632 100644
--- a/api-guide/settings.html
+++ b/api-guide/settings.html
@@ -434,6 +434,9 @@ If set to None
then generic filtering is disabled.
FORMAT_SUFFIX_KWARG
The name of a parameter in the URL conf that may be used to provide a format suffix.
Default: 'format'
+NUM_PROXIES
+An integer of 0 or more, that may be used to specify the number of application proxies that the API runs behind. This allows throttling to more accurately identify client IP addresses. If set to None
then less strict IP matching will be used by the throttle classes.
+Default: None
diff --git a/api-guide/throttling.html b/api-guide/throttling.html
index e0bb189c3..496424816 100644
--- a/api-guide/throttling.html
+++ b/api-guide/throttling.html
@@ -229,7 +229,7 @@ If any throttle check fails an exceptions.Throttled
exception will
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
- }
+ }
}
The rate descriptions used in DEFAULT_THROTTLE_RATES
may include second
, minute
, hour
or day
as the throttle period.
@@ -257,6 +257,11 @@ def example_view(request, format=None):
}
return Response(content)
+How clients are identified
+The X-Forwarded-For
and Remote-Addr
HTTP headers are used to uniquely identify client IP addresses for throttling. If the X-Forwarded-For
header is present then it will be used, otherwise the value of the Remote-Addr
header will be used.
+If you need to strictly identify unique client IP addresses, you'll need to first configure the number of application proxies that the API runs behind by setting the NUM_PROXIES
setting. This setting should be an integer of zero or more. If set to non-zero then the client IP will be identified as being the last IP address in the X-Forwarded-For
header, once any application proxy IP addresses have first been excluded. If set to zero, then the Remote-Addr
header will always be used as the identifying IP address.
+It is important to understand that if you configure the NUM_PROXIES
setting, then all clients behind a unique NAT'd gateway will be treated as a single client.
+Further context on how the X-Forwarded-For
header works, and identifing a remote client IP can be found here.
Setting up the cache
The throttle classes provided by REST framework use Django's cache backend. You should make sure that you've set appropriate cache settings. The default value of LocMemCache
backend should be okay for simple setups. See Django's cache documentation for more details.
If you need to use a cache other than 'default'
, you can do so by creating a custom throttle class and setting the cache
attribute. For example:
diff --git a/api-guide/viewsets.html b/api-guide/viewsets.html
index b154144ec..454d7d82f 100644
--- a/api-guide/viewsets.html
+++ b/api-guide/viewsets.html
@@ -186,7 +186,7 @@ a.fusion-poweredby {
Both of these come with a trade-off. Using regular views and URL confs is more explicit and gives you more control. ViewSets are helpful if you want to get up and running quickly, or when you have a large API and you want to enforce a consistent URL configuration throughout.
-Marking extra methods for routing
+Marking extra actions for routing
The default routers included with REST framework will provide routes for a standard set of create/retrieve/update/destroy style operations, as shown below:
class UserViewSet(viewsets.ViewSet):
"""
@@ -292,12 +292,13 @@ urlpatterns = router.urls
def destroy(self, request, pk=None):
pass
-If you have ad-hoc methods that you need to be routed to, you can mark them as requiring routing using the @link
or @action
decorators. The @link
decorator will route GET
requests, and the @action
decorator will route POST
requests.
+If you have ad-hoc methods that you need to be routed to, you can mark them as requiring routing using the @detail_route
or @list_route
decorators.
+The @detail_route
decorator contains pk
in its URL pattern and is intended for methods which require a single instance. The @list_route
decorator is intended for methods which operate on a list of objects.
For example:
from django.contrib.auth.models import User
-from rest_framework import viewsets
from rest_framework import status
-from rest_framework.decorators import action
+from rest_framework import viewsets
+from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializer
@@ -308,7 +309,7 @@ class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
- @action()
+ @detail_route(methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.DATA)
@@ -319,14 +320,21 @@ class UserViewSet(viewsets.ModelViewSet):
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
+
+ @list_route()
+ def recent_users(self, request):
+ recent_users = User.objects.all().order('-last_login')
+ page = self.paginate_queryset(recent_users)
+ serializer = self.get_pagination_serializer(page)
+ return Response(serializer.data)
-The @action
and @link
decorators can additionally take extra arguments that will be set for the routed view only. For example...
- @action(permission_classes=[IsAdminOrIsSelf])
+The decorators can additionally take extra arguments that will be set for the routed view only. For example...
+ @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
-The @action
decorator will route POST
requests by default, but may also accept other HTTP methods, by using the methods
argument. For example:
- @action(methods=['POST', 'DELETE'])
+Theses decorators will route GET
requests by default, but may also accept other HTTP methods, by using the methods
argument. For example:
+ @detail_route(methods=['post', 'delete'])
def unset_password(self, request, pk=None):
...
diff --git a/img/sponsors/2-wusawork.png b/img/sponsors/2-wusawork.png
new file mode 100644
index 000000000..5834729b9
Binary files /dev/null and b/img/sponsors/2-wusawork.png differ
diff --git a/index.html b/index.html
index f58cdff1a..b7a5a2c2c 100644
--- a/index.html
+++ b/index.html
@@ -252,7 +252,7 @@ a.fusion-poweredby {
REST framework requires the following:
- Python (2.6.5+, 2.7, 3.2, 3.3)
-- Django (1.3, 1.4, 1.5, 1.6)
+- Django (1.4.2+, 1.5, 1.6, 1.7)
The following packages are optional:
@@ -389,16 +389,9 @@ urlpatterns = patterns('',
- Credits
Development
-If you want to work on REST framework itself, clone the repository, then...
-Build the docs:
-./mkdocs.py
-
-Run the tests:
-./rest_framework/runtests/runtests.py
-
-To run the tests against all supported configurations, first install the tox testing tool globally, using pip install tox
, then simply run tox
:
-tox
-
+See the Contribution guidelines for information on how to clone
+the repository, run the test suite and contribute changes back to REST
+Framework.
Support
For support please see the REST framework discussion group, try the #restframework
channel on irc.freenode.net
, search the IRC archives, or raise a question on Stack Overflow, making sure to include the 'django-rest-framework' tag.
Paid support is available from DabApps, and can include work on REST framework core, or support with building your REST framework API. Please contact DabApps if you'd like to discuss commercial support options.
diff --git a/topics/2.4-accouncement.html b/topics/2.4-accouncement.html
index 92e21a5d0..0b4df1a88 100644
--- a/topics/2.4-accouncement.html
+++ b/topics/2.4-accouncement.html
@@ -3,17 +3,17 @@
REST framework 2.4 announcement - Django REST framework
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+