103django_rest-framework

 

目錄

django rest  framework. 1

serializers.Serializer. 1

serializers.ModelSerializer... 3

api FBV... 4

rest_framework.request.Requestrest_framework.response.Response... 5

rest_framework.decorators.api_viewrest_framework.views.APIView... 5

api CBVrest_framework.views.APIView... 6

api CBV,使用rest_framework.mixins... 7

api CBV,使用generics.ListCreateAPIViewgenerics.RetrieveUpdateDestroyAPIView... 8

分頁:... 9

認證:... 9

授權:... 10

 

 

 

django rest framework

 

django用來restful api的框架,風格完全和django一樣,使用起來像是django本身提供的;

 

https://www.django-rest-framework.org/

 

(webproject) C:\webproject\mysite>pip install djangorestframework

 

INSTALLED_APPS = [

    'rest_framework',

 

 

serializers.Serializer

rest_framework.serializers.Serializerdjango.forms.Form

功能一樣,都是將用戶提交的數據轉爲py數據結構,可用此來完成校驗;

 

Form用在post提交中的form表單;

Serializer用在用戶提交的json

 

 

from rest_framework import serializers

from .models import Author

 

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):

        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

 

 

底層實現:

>>> from books.serializer import AuthorSerializer

>>> from rest_framework.renderers import JSONRenderer   #py結構-->json

>>> from rest_framework.parsers import JSONParser   #json-->py結構

>>> from books.models import Author

>>> Author.objects.all()

<QuerySet [<Author: chai jowin>, <Author: dsfdfd sfdsfdsf>]>

>>> a = Author.objects.get(id=1)

>>> s = AuthorSerializer(a)

>>> s.data   #dict

{'last_name': 'jowin', 'email': '[email protected]', 'id': 1, 'first_name': 'chai'}

>>> content = JSONRenderer().render(s.data)

>>> content

b'{"id":1,"first_name":"chai","last_name":"jowin","email":"[email protected]"}'

 

>>> from django.utils.six import BytesIO

>>> stream = BytesIO(content)

>>> stream

<_io.BytesIO object at 0x00000000046389E8>

>>> data = JSONParser().parse(stream)

>>> data

{'last_name': 'jowin', 'email': '[email protected]', 'id': 1, 'first_name': 'chai'}

>>> s = AuthorSerializer(data=data)

>>> s

AuthorSerializer(data={'last_name': 'jowin', 'email': '[email protected]', 'id': 1, 'first_name': 'chai'}):

    id = IntegerField(read_only=True)

    first_name = CharField(max_length=100)

    last_name = CharField(allow_blank=True, max_length=100, required=False)

    email = EmailField(allow_blank=True, max_length=100, required=False)

>>> s.is_valid()

True

>>> s.validated_data   #返回ordereddict

OrderedDict([('first_name', 'chai'), ('last_name', 'jowin'), ('email', '[email protected]')])

>>> s.save()

<Author: chai jowin>

 

>>> Author.objects.all()

<QuerySet [<Author: chai jowin>, <Author: dsfdfd sfdsfdsf>, <Author: chai jowin>]>

>>> s = AuthorSerializer(Author.objects.all(), many=True)   #序列化多個對象時要加many=True,調用many_init()

>>> s.data

[OrderedDict([('id', 1), ('first_name', 'chai'), ('last_name', 'jowin'), ('email', '[email protected]')]), OrderedDict([('id', 2), ('first_name', 'dsfdfd'), ('la

st_name', 'sfdsfdsf'), ('email', '[email protected]')]), OrderedDict([('id', 3), ('first_name', 'chai'), ('last_name', 'jowin'), ('email', '[email protected]')])

]

 

 

serializers.ModelSerializer

 

rest_framework.serializers.ModelSerializerdjango.forms.ModelForm

 

 

class AuthorSerializer(serializers.ModelSerializer):

    class Meta:

        model = Author

        fields = ['id', 'first_name', 'last_name', 'email']

 

 

api FBV

 

from django.http import HttpResponse

from rest_framework.renderers import JSONRenderer

from rest_framework.parsers import JSONParser

from .serializer import AuthorSerializer

from .models import Author

from django.views.decorators.csrf import csrf_exempt

 

class JSONResponse(HttpResponse):   #可用django.http.JsonResponse

    def __init__(self, data, **kwargs):

        content = JSONRenderer().render(data)

        kwargs['content_type'] = 'application/json'

        super(JSONResponse, self).__init__(content, **kwargs)   #super().__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, safe=False)   # 默認safe=TrueIn order to allow non-dict objects to be serialized set the safe parameter to False.

 

    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):

    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)

 

 

    url(r'^authors/$', api.author_list, name='author_list'),

    url(r'^authors/(?P<pk>[0-9]+)/$', api.author_detail, name='author_detail'),

 

 

rest_framework.request.Requestrest_framework.response.Response

 

request.POST  # Only handles form data.  Only works for 'POST' method.

request.data  # Handles arbitrary data.  Works for 'POST', 'PUT' and 'PATCH' methods.

 

 

return Response(data)  # Renders to content type as requested by the client.根據客戶端的請求渲染內容類型

 

 

rest_framework.decorators.api_viewrest_framework.views.APIView

 

The @api_view decorator for working with function based views.

The APIView class for working with class-based views.   #django.views.View

 

例,@api_view

@api_view(['GET', 'POST'])   #只作爲接口使用,用browser訪問報WrappedAttributeError'CSRFCheck' object has no attribute 'process_request'

@csrf_exempt

def author_list(request):

    if request.method == 'GET':

        authors = Author.objects.all()

        serializer = AuthorSerializer(authors, many=True)

        # return JSONResponse(serializer.data)

        # return JsonResponse(serializer.data, safe=False)

        return Response(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 Response(serializer.data, status=201)

        # return JsonResponse(serializer.errors, status=400)

        return Response(serializer.errors, status=400)

 

postmanGETPOST

 

 

api CBVrest_framework.views.APIView

 

 

from rest_framework.views import APIView

from rest_framework import status

from django.http import Http404

 

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)

 

 

    # url(r'^authors/$', api.author_list, name='author_list'),

    url(r'^authors/$', AuthorList.as_view()),

    # url(r'^authors/(?P<pk>[0-9]+)/$', api.author_detail, name='author_detail'),

    url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetail.as_view()),

 

 

api CBV,使用rest_framework.mixins

 

from rest_framework import mixins

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 put(self, request, *args, **kwargs):

        return self.update(request, *args, **kwargs)

 

    def delete(self, request, *args, **kwargs):

        return self.destroy(request, *args, **kwargs)

 

 

api CBV,使用generics.ListCreateAPIViewgenerics.RetrieveUpdateDestroyAPIView

 

 

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

 

1.jpg

postman測試時,PUT方法注意要用JSON

 

 

分頁:

REST_FRAMEWORK = {

    # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',

    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',

    "PAGE_SIZE": 2,

 

 

認證:

django支持認證方式:

Basic,默認;

Session

Token

自定義認證;

 

2.jpg

默認用Basic認證,輸入UsernamePassword,會自動生成到Headers中,用base64加密;

3.jpg

 

 

例,使用token認證:

INSTALLED_APPS = [

    'rest_framework.authtoken',

 

REST_FRAMEWORK = {

    "DEFAULT_AUTHENTICATION_CLASSES": (

        # 'rest_framework.authentication.BasicAuthentication',

        # 'rest_framework.authentication.SessionAuthentication',

        'rest_framework.authentication.TokenAuthentication',

    )

}

 

(webproject) C:\webproject\mysite>python manage.py makemigrations

(webproject) C:\webproject\mysite>python manage.py migrate

 

>>> from django.contrib.auth.models import User

>>> from rest_framework.authtoken.models import Token

>>> t = Token.objects.create(user=User.objects.get(id=1))

>>> t.key

'219c0ec96617256b93b36d0ab95b70e7c893ac1b'

 

4.jpg

 

 

例,用session認證:

5.jpg

KEYCookieVALUE中粘貼網頁中Networkcsrftoken

 

 

授權:

 

https://www.django-rest-framework.org/api-guide/permissions/#api-reference

 

rest_framework內置權限:

AllowAny

IsAuthenticated

IsAdminUser

IsAuthenticatedOrReadOnly

DjangoModelPermissions

DjangoModelPermissionsOrAnonReadOnly

DjangoObjectPermissions

 

REST_FRAMEWORK = {

    "PAGE_SIZE": 1,

    "DEFAULT_AUTHENTICATION_CLASSES": (

        # 'rest_framework.authentication.BasicAuthentication',

        # 'rest_framework.authentication.SessionAuthentication',

        'rest_framework.authentication.TokenAuthentication',

        'rest_framework.permissions.IsAuthenticated',   #全局配置默認權限

    )

}

 

 

例,view中使用權限控制:

from rest_framework import generics

from rest_framework import permissions

 

class AuthorList(generics.ListCreateAPIView):

    queryset = Author.objects.all()

    serializer_class = AuthorSerializer

    permission_classes = (permissions.IsAuthenticated,)   #多個是and的關係

 

 

例,自定義權限:

from rest_framework import generics

from rest_framework import permissions

 

class IsSuperUser(permissions.BasePermission):   #繼承permissions.BasePermission,重寫has_permission()

    def has_permission(self, request, view):

        return request.user.is_superuser()

 

class AuthorList(generics.ListCreateAPIView):

    queryset = Author.objects.all()

    serializer_class = AuthorSerializer

    # permission_classes = (permissions.IsAuthenticated,)

    permission_classes = (IsSuperUser,)

 

 

rest_framework.viewsetsrest_framework.routers.DefaultRouter

 

ViewSetView,不同之處在於ViewSet提供readupdate之類的操作,而不是getput等方法處理程序;當它被實例化成一組視圖的時候,通過使用Router類來處理自己定義的url

 

 

例:

from rest_framework import viewsets

 

class AuthorViewSet(viewsets.ReadOnlyModelViewSet):   #僅提供listdetail操作

    queryset = Author.objects.all()

    serializer_class = AuthorSerializer

    # permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

 

 

例:

from rest_framework import viewsets

 

class AuthorViewSet(viewsets.ModelViewSet):   #提供list|create|retrieve|update|destroy

    queryset = Author.objects.all()

    serializer_class = AuthorSerializer

# permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

 

 

author_list = AuthorViewSet.as_view({

    'get': 'list',

    'post': 'create'

})

 

author_detail = AuthorViewSet.as_view({

    'get': 'retrieve',

    'put': 'update',

    'pathch': 'partial_update',

    'delete': 'destroy',

})

 

    # url(r'^authors/$', api.author_list, name='author_list'),

    # url(r'^authors/$', AuthorList.as_view()),

    url(r'^authors/$', author_list, name='author-list'),

    # url(r'^authors/(?P<pk>[0-9]+)/$', api.author_detail, name='author_detail'),

    # url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetail.as_view()),

    url(r'^authors/(?P<pk>[0-9]+)/$', author_detail, name='author-detail'),

 

 

例,使用routers

from rest_framework import viewsets

 

class AuthorViewSet(viewsets.ModelViewSet):

    queryset = Author.objects.all()

    serializer_class = AuthorSerializer

# permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

 

 

router = DefaultRouter()

router.register(r'authors', AuthorViewSet)

 

 

urlpatterns = [

         ……

]

 

urlpatterns += router.urls   #方式1

# urlpatterns += [   #方式2

#     url(r'^', include(router.urls)),

# ]

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章