Install RestFramework
$ pip install djangorestframework # settings.py INSTALLED_APPS = ( ... 'rest_framework', )
Create Serializer class
from rest_framework import serializers from .models import Book, Author, Publisher class AuthorSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) first_name = serializers.CharField(max_length=100) last_name = serializers.CharField(required=False, allow_blank=True, max_length=100) email = serializers.EmailField(required=False, allow_blank=True, max_length=100) def create(self, validated_data): # Create and return a new 'Snippet' instance, given the validated data. return Author.objects.create(**validated_data) def update(self, instance, validated_data): instance.first_name = validated_data.get('first_name', instance.first_name) instance.last_name = validated_data.get('last_name', instance.last_name) instance.email = validated_data.get('email', instance.email) instance.save() return instance
Use the provided API
>>> from books.serializers import * >>> from rest_framework.renderers import JSONRenderer >>> from rest_framework.parsers import JSONParser >>> g = Author.objects.create(first_name='guang', last_name='hongwei', email='ibuler@qq.com') >>> m = Author.objects.create(first_name='ma', last_name='ge', email='ma@magedu.com') >>> serializer = AuthorSerializer(g) >>> serializer.data ReturnDict([('id', 1), ('first_name', u'guang'), ('last_name', u'hongwei'), ('email', u'ibuler@qq.com')]) >>> content = JSONRenderer().render(serializer.data) >>> content '{"id": 1, "first_name": "guang", "last_name": "hongwei", "email": "ibuler@qq.com"}' >>> from django.utils.six import BytesIO >>> content = '{"first_name": "li", "last_name": "xueming", "email": "comyn@magedu.com"}' >>> stream = BytesIO(content) >>> data = JSONParser().parse(stream) >>> data {u'email': u'comyn@magedu.com', u'first_name': u'li', u'last_name': u'xueming'} >>> serializer = AuthorSerializer(data=data) >>> serializer.is_valid() >>> serializer.data # Not a Python type ReturnDict([('first_name', 'li'), ('last_name', 'xueming'), ('email', 'comyn@magedu.com')]) >>> serializer.validated_data # Convert to Python type OrderedDict([('first_name', 'li'), ('last_name', 'xueming'), ('email', 'comyn@magedu.com')]) >>> serializer.save() >>> serializer = AuthorSerializer(Author.objects.all(), many=True) >>> serializer.data
Using ModelSerializers
class AuthorSerializer(serializers.ModelSerializer): class Meta: model = Author fields = ('id', 'first_name', 'last_name', 'email')
API Function View
from django.http import HttpResponse from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser from .models import Author from .serializers import AuthorSerializer class JSONResponse(HttpResponse): # An HttpResponse that renders its content into JSON. def __init__(self, data, **kwargs): content = JSONRenderer().render(data) kwargs['content-type'] = 'application/json' super(JSONResponse, self).__init__(content, **kwargs) @csrf_exempt def author_list(request): if request.method == 'GET': authors = Author.objects.all() serializer = AuthorSerializer(authors, many=True) return JSONResponse(serializer.data) elif request.method == 'POST': data = JSONParser().parse(request) serializer = AuthorSerializer(data=data) if serializer.is_valid(): serializer.save() return JSONResponse(serializer.data, status=201) return JSONResponse(serializer.errors, status=400) @csrf_exempt def author_detail(request, pk): # Retrieve, update or delete a code snippet. try: author = Author.objects.get(pk=pk) except Author.DoesNotExist: return JSONResponse('', status=404) if request.method == 'GET': serializer = AuthorSerializer(author) return JSONResponse(serializer.data) elif request.method == 'PUT': data = JSONParser().parse(request) serializer = AuthorSerializer(author, data=data) if serializer.is_valid(): serializer.save() return JSONResponse(serializer.data) return JSONResponse(serializer.errors, status=400) elif request.method == 'DELETE': author.delete() return JSONResponse('', status=204) # urls.py urlpatterns = [ url(r'^authors/$', views.author_list, name='author_list'), url(r'^authors/(?P<pk>[0-9]+)/$', views.author_detail, name='author_detail'), ]
Request And Response
- request
- request.POST # Only handles form data. Only works for 'POST' method.
- request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
- Response(data) # Renders to content type as requested by the client.
Packaging API View
from rest_framework.decorators import api_view ... @api_view(['GET', 'POST']) def author_list(request): pass
Using class based views
from django.http import Http404 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class AuthorList(APIView): def get(self, request, format=None): authors = Author.objects.all() serializer = AuthorSerializer(authors, many=True) return Response(serializer.data) def post(self, request, format=None): serializer = AuthorSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class AuthorDetail(APIView): def get_object(self, pk): try: return Author.objects.get(pk=pk) except Author.DoesNotExist: return Http404 def get(self, request, pk, format=None): author = self.get_object(pk) serializer = AuthorSerializer(author) return Response(serializer.data) def put(self, request, pk, format=None): author = self.get_object(pk) serializer = AuthorSerializer(author, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, pk, format=None): author = self.get_object(pk) author.delete() return Response(status=status.HTTP_204_NO_CONTENT)
- APIView
Using Mixin
from rest_framework import mixins # from rest_framework.mixins import CreateModelMixin, ListModelMixin from rest_framework import generics class AuthorList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): queryset = Author.objects.all() serializer_class = AuthorSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class AuthorDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): queryset = Author.objects.all() serializer_class = AuthorSerializer def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class AuthorDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): queryset = Author.objects.all() serializer_class = AuthorSerializer def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs)
Using generic class based views
... from rest_framework import generics class AuthorList(generics.ListCreateAPIView): queryset = Author.objects.all() serializer_class = AuthorSerializer class AuthorDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Author.objects.all() serializer_class = AuthorSerializer
paging
# settings.py REST_FRAMEWORK = { 'PAGE_SIZE': 10 }
Authentication and authorization
See: http://www.django-rest-framework.org/api-guide/permissions/ ා API reference
- rest framework built in permissions
- AllowAny
- IsAuthenticated
- IsAdminUser
- IsAuthenticatedOrReadOnly
- DjangoModelPermissions
- DjangoModelPermissionsOrAnonReadOnly
- DjangoObjectPermissions
- Global configuration default permissions
# settings.py REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
- Use authentication in view
# views.py from rest_framework import permissions class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer permission_classes = (permissions.IsAuthenticated, )
- Custom permissions
from rest_framework import permissions class IsSuperUser(permissions.BasePermission): def has_permission(self, request, view): return request.user.is_superuser() # views from .permissions import IsSuperUser class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer permission_classes = (IsSuperUser,)
- Django supports authentication methods
- Basic authentication
- Session authentication
- Token authentication
- Custom authentication
Djangorest framework uses Basic authentication by default
# settings.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', # 'rest_framework.authentication.SessionAuthentication', ) }
- Using Basic authentication
Post man request, fill in Authorization, user name admin, password django user admin - Using token authentication
- Installed Apus added rest framework.authtoken
INSTALLED_APPS = ( ... 'rest_framework.authtoken' )
- Enable TOKEN authentication
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.TokenAuthentication', ) }
- Create token
>>> from rest_framework.authtoken.models import Token >>> token = Token.objects.create(user=...) >>> print(token.key)
- Use Token to request postman and set Authorization header
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
Viewset and Router
# views.py from rest_framework import viewsets from .models import Author from .serializers import AuthorSerializer # version 1 class AuthorViewSet(viewsets.ReadOnlyModelViewSet): # This viewset automatically provides 'list' and 'detail' actions. queryset = Author.objects.all() serializer_class = AuthorSerializer # version 2 class AuthorViewSet(viewsets.ModelViewSet): # This viewset automatically provides 'list', 'create', 'retrieve', 'update' and 'destroy' actions. queryset = Author.objects.all() serializer_class = AuthorSerializer permission_classes = (permissions.IsAuthenticationOrReadOnly,) #urls.py from . import views from rest_framework import renders # version 1 author_list = AuthorViewSet.as_view({ 'get': 'list', 'post': 'create', }) author_detail = AuthorViewSet.as_view({ 'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy', }) urlpatterns += [ url(r'^authors/$', author_list, name='author-list'), url(r'^authors/(?P<pk>[0-9]+)/$', author_detail, name='author-detail'), ] # version 2 user Routers from django.conf.urls import url, include from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register(r'authors', views.AuthorViewSet) urlpatterns = [ url(r'^publisher/(?P<pk>[0-9]+)/$', views.PublisherDetail.as_view()), ] urlpatterns += [ url(r'^', include(router.urls)), ] urlpatterns += router.urls
227 original articles published, praised 605, and 1.3 million visitors+