diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index b1ab46227..f30b16ed5 100755 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -46,6 +46,11 @@ The default authentication schemes may be set globally, using the `DEFAULT_AUTHE You can also set the authentication scheme on a per-view or per-viewset basis, using the `APIView` class based views. + from rest_framework.authentication import SessionAuthentication, BasicAuthentication + from rest_framework.permissions import IsAuthenticated + from rest_framework.response import Response + from rest_framework.views import APIView + class ExampleView(APIView): authentication_classes = (SessionAuthentication, BasicAuthentication) permission_classes = (IsAuthenticated,) @@ -157,11 +162,16 @@ The `curl` command line tool may be useful for testing token authenticated APIs. If you want every user to have an automatically generated Token, you can simply catch the User's `post_save` signal. + from django.dispatch import receiver + from rest_framework.authtoken.models import Token + @receiver(post_save, sender=User) def create_auth_token(sender, instance=None, created=False, **kwargs): if created: Token.objects.create(user=instance) +Note that you'll want to ensure you place this code snippet in an installed `models.py` module, or some other location that will be imported by Django on startup. + If you've already created some users, you can generate tokens for all existing users like this: from django.contrib.auth.models import User @@ -336,6 +346,10 @@ If the `.authenticate_header()` method is not overridden, the authentication sch The following example will authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'. + from django.contrib.auth.models import User + from rest_framework import authentication + from rest_framework import exceptions + class ExampleAuthentication(authentication.BaseAuthentication): def authenticate(self, request): username = request.META.get('X_USERNAME') diff --git a/docs/api-guide/content-negotiation.md b/docs/api-guide/content-negotiation.md index 2a7742786..94dd59cac 100644 --- a/docs/api-guide/content-negotiation.md +++ b/docs/api-guide/content-negotiation.md @@ -54,6 +54,8 @@ The `select_renderer()` method should return a two-tuple of (renderer instance, The following is a custom content negotiation class which ignores the client request when selecting the appropriate parser or renderer. + from rest_framework.negotiation import BaseContentNegotiation + class IgnoreClientContentNegotiation(BaseContentNegotiation): def select_parser(self, request, parsers): """ @@ -77,6 +79,10 @@ The default content negotiation class may be set globally, using the `DEFAULT_CO You can also set the content negotiation used for an individual view, or viewset, using the `APIView` class based views. + from myapp.negotiation import IgnoreClientContentNegotiation + from rest_framework.response import Response + from rest_framework.views import APIView + class NoNegotiationView(APIView): """ An example view that does not perform content negotiation. diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index d69730c98..962c49e2a 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -78,6 +78,9 @@ A generic, **read-only** field. You can use this field for any attribute that d For example, using the following model. + from django.db import models + from django.utils.timezone import now + class Account(models.Model): owner = models.ForeignKey('auth.user') name = models.CharField(max_length=100) @@ -85,13 +88,14 @@ For example, using the following model. payment_expiry = models.DateTimeField() def has_expired(self): - now = datetime.datetime.now() - return now > self.payment_expiry + return now() > self.payment_expiry A serializer definition that looked like this: + from rest_framework import serializers + class AccountSerializer(serializers.HyperlinkedModelSerializer): - expired = Field(source='has_expired') + expired = serializers.Field(source='has_expired') class Meta: fields = ('url', 'owner', 'name', 'expired') @@ -125,12 +129,11 @@ The `ModelField` class is generally intended for internal use, but can be used b This is a read-only field. It gets its value by calling a method on the serializer class it is attached to. It can be used to add any sort of data to the serialized representation of your object. The field's constructor accepts a single argument, which is the name of the method on the serializer to be called. The method should accept a single argument (in addition to `self`), which is the object being serialized. It should return whatever you want to be included in the serialized representation of the object. For example: - from rest_framework import serializers from django.contrib.auth.models import User from django.utils.timezone import now + from rest_framework import serializers class UserSerializer(serializers.ModelSerializer): - days_since_joined = serializers.SerializerMethodField('get_days_since_joined') class Meta: diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 05c997a39..649462da7 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -20,6 +20,10 @@ You can do so by filtering based on the value of `request.user`. For example: + from myapp.models import Purchase + from myapp.serializers import PurchaseSerializer + from rest_framework import generics + class PurchaseList(generics.ListAPIView) serializer_class = PurchaseSerializer @@ -90,6 +94,11 @@ The default filter backends may be set globally, using the `DEFAULT_FILTER_BACKE You can also set the filter backends on a per-view, or per-viewset basis, using the `GenericAPIView` class based views. + from django.contrib.auth.models import User + from myapp.serializers import UserSerializer + from rest_framework import filters + from rest_framework import generics + class UserListView(generics.ListAPIView): queryset = User.objects.all() serializer = UserSerializer @@ -150,6 +159,11 @@ This will automatically create a `FilterSet` class for the given fields, and wil For more advanced filtering requirements you can specify a `FilterSet` class that should be used by the view. For example: + import django_filters + from myapp.models import Product + from myapp.serializers import ProductSerializer + from rest_framework import generics + class ProductFilter(django_filters.FilterSet): min_price = django_filters.NumberFilter(lookup_type='gte') max_price = django_filters.NumberFilter(lookup_type='lte') diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index 32a4feef4..7f754df8c 100755 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -17,6 +17,11 @@ If the generic views don't suit the needs of your API, you can drop down to usin Typically when using the generic views, you'll override the view, and set several class attributes. + from django.contrib.auth.models import User + from myapp.serializers import UserSerializer + from rest_framework import generics + from rest_framework.permissions import IsAdminUser + class UserList(generics.ListCreateAPIView): queryset = User.objects.all() serializer_class = UserSerializer diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index 912ce41bd..ca0174b76 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -13,6 +13,7 @@ REST framework includes a `PaginationSerializer` class that makes it easy to ret Let's start by taking a look at an example from the Django documentation. from django.core.paginator import Paginator + objects = ['john', 'paul', 'george', 'ringo'] paginator = Paginator(objects, 2) page = paginator.page(1) @@ -22,6 +23,7 @@ Let's start by taking a look at an example from the Django documentation. At this point we've got a page object. If we wanted to return this page object as a JSON response, we'd need to provide the client with context such as next and previous links, so that it would be able to page through the remaining results. from rest_framework.pagination import PaginationSerializer + serializer = PaginationSerializer(instance=page) serializer.data # {'count': 4, 'next': '?page=2', 'previous': None, 'results': [u'john', u'paul']} @@ -114,6 +116,9 @@ You can also override the name used for the object list field, by setting the `r 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. + from rest_framework import pagination + from rest_framework import serializers + class LinksSerializer(serializers.Serializer): next = pagination.NextPageField(source='*') prev = pagination.PreviousPageField(source='*') @@ -135,7 +140,7 @@ To have your custom pagination serializer be used by default, use the `DEFAULT_P Alternatively, to set your custom pagination serializer on a per-view basis, use the `pagination_serializer_class` attribute on a generic class based view: - class PaginatedListView(ListAPIView): + class PaginatedListView(generics.ListAPIView): model = ExampleModel pagination_serializer_class = CustomPaginationSerializer paginate_by = 10 diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index 5bd79a317..d3c42b1c2 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -37,6 +37,10 @@ The default set of parsers may be set globally, using the `DEFAULT_PARSER_CLASSE You can also set the renderers used for an individual view, or viewset, using the `APIView` class based views. + from rest_framework.parsers import YAMLParser + from rest_framework.response import Response + from rest_framework.views import APIView + class ExampleView(APIView): """ A view that can accept POST requests with YAML content. diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index c6372f981..a3d86ed49 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -47,6 +47,10 @@ If not specified, this setting defaults to allowing unrestricted access: You can also set the authentication policy on a per-view, or per-viewset basis, using the `APIView` class based views. + from rest_framework.permissions import IsAuthenticated + from rest_framework.responses import Response + from rest_framework.views import APIView + class ExampleView(APIView): permission_classes = (IsAuthenticated,) @@ -157,6 +161,8 @@ For more details see the [2.2 release announcement][2.2-announcement]. The following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted. + from rest_framework import permissions + class BlacklistPermission(permissions.BasePermission): """ Global permission check for blacklisted IPs. diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 829a3c548..aa14bc725 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -76,7 +76,7 @@ This field is read only. For example, the following serializer: class AlbumSerializer(serializers.ModelSerializer): - tracks = PrimaryKeyRelatedField(many=True, read_only=True) + tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True) class Meta: model = Album @@ -110,8 +110,8 @@ By default this field is read-write, although you can change this behavior using For example, the following serializer: class AlbumSerializer(serializers.ModelSerializer): - tracks = HyperlinkedRelatedField(many=True, read_only=True, - view_name='track-detail') + tracks = serializers.HyperlinkedRelatedField(many=True, read_only=True, + view_name='track-detail') class Meta: model = Album @@ -148,7 +148,8 @@ By default this field is read-write, although you can change this behavior using For example, the following serializer: class AlbumSerializer(serializers.ModelSerializer): - tracks = SlugRelatedField(many=True, read_only=True, slug_field='title') + tracks = serializers.SlugRelatedField(many=True, read_only=True, + slug_field='title') class Meta: model = Album @@ -183,7 +184,7 @@ When using `SlugRelatedField` as a read-write field, you will normally want to e This field can be applied as an identity relationship, such as the `'url'` field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer: class AlbumSerializer(serializers.HyperlinkedModelSerializer): - track_listing = HyperlinkedIdentityField(view_name='track-list') + track_listing = serializers.HyperlinkedIdentityField(view_name='track-list') class Meta: model = Album diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index bb3d20159..7fc1fc1fd 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -30,11 +30,16 @@ The default set of renderers may be set globally, using the `DEFAULT_RENDERER_CL You can also set the renderers used for an individual view, or viewset, using the `APIView` class based views. + from django.contrib.auth.models import User + from rest_framework.renderers import JSONRenderer, YAMLRenderer + from rest_framework.response import Response + from rest_framework.views import APIView + class UserCountView(APIView): """ - A view that returns the count of active users, in JSON or JSONp. + A view that returns the count of active users, in JSON or YAML. """ - renderer_classes = (JSONRenderer, JSONPRenderer) + renderer_classes = (JSONRenderer, YAMLRenderer) def get(self, request, format=None): user_count = User.objects.filter(active=True).count() diff --git a/docs/api-guide/reverse.md b/docs/api-guide/reverse.md index 942623666..383eca4ce 100644 --- a/docs/api-guide/reverse.md +++ b/docs/api-guide/reverse.md @@ -27,13 +27,13 @@ Has the same behavior as [`django.core.urlresolvers.reverse`][reverse], except t You should **include the request as a keyword argument** to the function, for example: - import datetime from rest_framework.reverse import reverse from rest_framework.views import APIView + from django.utils.timezone import now class APIRootView(APIView): def get(self, request): - year = datetime.datetime.now().year + year = now().year data = { ... 'year-summary-url': reverse('year-summary', args=[year], request=request) diff --git a/docs/api-guide/routers.md b/docs/api-guide/routers.md index 072a2e79a..fb48197e9 100644 --- a/docs/api-guide/routers.md +++ b/docs/api-guide/routers.md @@ -14,6 +14,8 @@ REST framework adds support for automatic URL routing to Django, and provides yo Here's an example of a simple URL conf, that uses `DefaultRouter`. + from rest_framework import routers + router = routers.SimpleRouter() router.register(r'users', UserViewSet) router.register(r'accounts', AccountViewSet) @@ -40,6 +42,9 @@ The example above would generate the following URL patterns: Any methods on the viewset decorated with `@link` or `@action` 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 + @action(permission_classes=[IsAdminOrIsSelf]) def set_password(self, request, pk=None): ... @@ -120,6 +125,8 @@ The arguments to the `Route` named tuple are: 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 + class ReadOnlyRouter(SimpleRouter): """ A router for read-only APIs, which doesn't use trailing slashes. diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index bbc8d019d..d9fd46437 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -28,6 +28,8 @@ We'll declare a serializer that we can use to serialize and deserialize `Comment Declaring a serializer looks very similar to declaring a form: + from rest_framework import serializers + class CommentSerializer(serializers.Serializer): email = serializers.EmailField() content = serializers.CharField(max_length=200) @@ -59,6 +61,8 @@ We can now use `CommentSerializer` to serialize a comment, or list of comments. At this point we've translated the model instance into Python native datatypes. To finalise the serialization process we render the data into `json`. + from rest_framework.renderers import JSONRenderer + json = JSONRenderer().render(serializer.data) json # '{"email": "leila@example.com", "content": "foo bar", "created": "2012-08-22T16:20:09.822"}' @@ -67,6 +71,9 @@ At this point we've translated the model instance into Python native datatypes. Deserialization is similar. First we parse a stream into Python native datatypes... + from StringIO import StringIO + from rest_framework.parsers import JSONParser + stream = StringIO(json) data = JSONParser().parse(stream) diff --git a/docs/api-guide/status-codes.md b/docs/api-guide/status-codes.md index db2e059c3..409f659b2 100644 --- a/docs/api-guide/status-codes.md +++ b/docs/api-guide/status-codes.md @@ -9,6 +9,7 @@ Using bare status codes in your responses isn't recommended. REST framework includes a set of named constants that you can use to make more code more obvious and readable. from rest_framework import status + from rest_framework.response import Response def empty_view(self): content = {'please move along': 'nothing to see here'} diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md index 92f8d54aa..b3880f8f0 100644 --- a/docs/api-guide/testing.md +++ b/docs/api-guide/testing.md @@ -16,6 +16,8 @@ Extends [Django's existing `RequestFactory` class][requestfactory]. The `APIRequestFactory` class supports an almost identical API to Django's standard `RequestFactory` class. This means the that standard `.get()`, `.post()`, `.put()`, `.patch()`, `.delete()`, `.head()` and `.options()` methods are all available. + from rest_framework.test import APIRequestFactory + # Using the standard RequestFactory API to create a form POST request factory = APIRequestFactory() request = factory.post('/notes/', {'title': 'new idea'}) @@ -49,6 +51,8 @@ For example, using `APIRequestFactory`, you can make a form PUT request like so: Using Django's `RequestFactory`, you'd need to explicitly encode the data yourself: + from django.test.client import encode_multipart, RequestFactory + factory = RequestFactory() data = {'title': 'remember to email dave'} content = encode_multipart('BoUnDaRyStRiNg', data) @@ -72,6 +76,12 @@ To forcibly authenticate a request, use the `force_authenticate()` method. The signature for the method is `force_authenticate(request, user=None, token=None)`. When making the call, either or both of the user and token may be set. +For example, when forcibly authenticating using a token, you might do something like the following: + + user = User.objects.get(username='olivia') + request = factory.get('/accounts/django-superstars/') + force_authenticate(request, user=user, token=user.token) + --- **Note**: When using `APIRequestFactory`, the object that is returned is Django's standard `HttpRequest`, and not REST framework's `Request` object, which is only generated once the view is called. @@ -105,6 +115,8 @@ Extends [Django's existing `Client` class][client]. The `APIClient` class supports the same request interface as `APIRequestFactory`. This means the that standard `.get()`, `.post()`, `.put()`, `.patch()`, `.delete()`, `.head()` and `.options()` methods are all available. For example: + from rest_framework.test import APIClient + client = APIClient() client.post('/notes/', {'title': 'new idea'}, format='json') @@ -131,8 +143,11 @@ The `login` method is appropriate for testing APIs that use session authenticati The `credentials` method can be used to set headers that will then be included on all subsequent requests by the test client. + from rest_framework.authtoken.models import Token + from rest_framework.test import APIClient + # Include an appropriate `Authorization:` header on all requests. - token = Token.objects.get(username='lauren') + token = Token.objects.get(user__username='lauren') client = APIClient() client.credentials(HTTP_AUTHORIZATION='Token ' + token.key) @@ -190,10 +205,10 @@ You can use any of REST framework's test case classes as you would for the regul Ensure we can create a new account object. """ url = reverse('account-list') - data = {'name': 'DabApps'} + expected = {'name': 'DabApps'} response = self.client.post(url, data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) - self.assertEqual(response.data, data) + self.assertEqual(response.data, expected) --- diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index 56f32f58a..42f9c228d 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -43,6 +43,10 @@ The rate descriptions used in `DEFAULT_THROTTLE_RATES` may include `second`, `mi You can also set the throttling policy on a per-view or per-viewset basis, using the `APIView` class based views. + from rest_framework.response import Response + from rest_framework.throttling import UserRateThrottle + from rest_framework.views import APIView + class ExampleView(APIView): throttle_classes = (UserRateThrottle,) diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md index 0c68afb0b..61f9d2f85 100644 --- a/docs/api-guide/viewsets.md +++ b/docs/api-guide/viewsets.md @@ -19,6 +19,12 @@ Typically, rather than explicitly registering the views in a viewset in the urlc Let's define a simple viewset that can be used to list or retrieve all the users in the system. + from django.contrib.auth.models import User + from django.shortcuts import get_object_or_404 + from myapps.serializers import UserSerializer + from rest_framework import viewsets + from rest_framewor.responses import Response + class UserViewSet(viewsets.ViewSet): """ A simple ViewSet that for listing or retrieving users. @@ -41,6 +47,9 @@ If we need to, we can bind this viewset into two separate views, like so: Typically we wouldn't do this, but would instead register the viewset with a router, and allow the urlconf to be automatically generated. + from myapp.views import UserViewSet + from rest_framework.routers import DefaultRouter + router = DefaultRouter() router.register(r'users', UserViewSet) urlpatterns = router.urls