美文网首页Drf/Django开发记录
Drf官网教程(三) - CBV

Drf官网教程(三) - CBV

作者: dyq666 | 来源:发表于2018-06-23 12:32 被阅读54次

    目录

    1. 将FBV改为CBV
    2. 使用Mixins
    3. 使用generic中更上层的封装类

    0. 概述

    使用CBV的好处是可以减少代码的重复量。

    1. 将FBV改为CBV

    • 修改snippets/views.py

    大部分代码都没有变动,直接将原来的代码粘到类中,进行一些小的修改即可。

    from django.http import Http404
    from rest_framework import status
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from snippets.models import Snippet
    from snippets.serializers import SnippetSerializer
    
    
    class SnippetList(APIView):
        """list, create"""
        def get(self, request, format=None):
            snippets = Snippet.objects.all()
            serializer = SnippetSerializer(snippets, many=True)
            return Response(serializer.data)
    
        def post(self, request, format=None):
            serializer = SnippetSerializer(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 SnippetDetail(APIView):
        """retrive, update, delete"""
        def get_object(self, pk):
            """根据id获取Model实例"""
            try:
                return Snippet.objects.get(pk=pk)
            except Snippet.DoesNotExist:
                raise Http404
    
        def get(self, request, pk, format=None):
            snippet = self.get_object(pk)
            serializer = SnippetSerializer(snippet)
            return Response(serializer.data)
    
        def put(self, request, pk, format=None):
            snippet = self.get_object(pk)
            serializer = SnippetSerializer(snippet, data=request.data)
    
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
        def delete(self, request, pk, format=None):
            snippet = self.get_object(pk=pk)
            snippet.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
    
    
    • 修改snippets/urls.py
    ...
    
    urlpatterns = format_suffix_patterns([
        url(r'^$', views.SnippetList.as_view()),
        url(r'^(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view())
    ])
    

    2. 使用Mixins

    大部分的view都要完成上面这些固定的代码,因而Drf将这些固定部分放到了mixins中。只要使用GenericAPIView + mixin就能省去这部分。但是要完成下面这两步:

    1. 指明操作的model集合和序列化类
    2. mixins提供的是ACTION(list, retrieve, create, update, destroy),而view的入口是HTTP-METHOD,所以需要手动将这些METHOD与ACTION绑定。
    from rest_framework import mixins
    from rest_framework.generics import GenericAPIView
    
    from snippets.models import Snippet
    from snippets.serializers import SnippetSerializer
    
    
    class SnippetList(mixins.ListModelMixin,
                      mixins.CreateModelMixin,
                      GenericAPIView):
        """
        get:list 
        post:create
        """
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer
    
        def get(self, request, *args, **kwargs):
            return self.list(self, request, *args, **kwargs)
    
        def post(self, request, *args, **kwargs):
            return self.create(self, request, *args, **kwargs)
    
    
    class SnippetDetail(mixins.RetrieveModelMixin,
                        mixins.UpdateModelMixin,
                        mixins.DestroyModelMixin,
                        GenericAPIView):
        """
        get:retrieve
        put:update
        delete:destroy
        """
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer
    
        def get(self, request, *args, **kwargs):
            return self.retrieve(self, request, *args, **kwargs)
    
        def put(self, request, *args, **kwargs):
            return self.update(self, request, *args, **kwargs)
    
        def delete(self, request, *args, **kwargs):
            return self.destroy(self, request, *args, **kwargs)
    

    3. 使用generic中更上层的封装类

    由于大部分的绑定操作也是固定的,所以generics中提供了一些已经绑定过的类。

    • 修改views.py
    from rest_framework import generics
    
    from snippets.models import Snippet
    from snippets.serializers import SnippetSerializer
    
    
    class SnippetList(generics.ListCreateAPIView):
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer
    
    
    class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer
    
    • 通过源码结构查看generics提供了哪些类
    image.png

    如果这些都不满足要求的话,可以模仿这些类,手动定制。
    比如定制一个update-put,destroy-delete的类。

    class UpdateDestroyAPIView(mixins.UpdateModelMixin,
                                       mixins.DestroyModelMixin,
                                       GenericAPIView):
        """
        Concrete view for updating or deleting a model instance.
        """
        def put(self, request, *args, **kwargs):
            return self.update(request, *args, **kwargs)
    
        def delete(self, request, *args, **kwargs):
            return self.destroy(request, *args, **kwargs)
    

    现在代码变得非常简明了!

    相关文章

      网友评论

        本文标题:Drf官网教程(三) - CBV

        本文链接:https://www.haomeiwen.com/subject/nnuryftx.html