zoukankan      html  css  js  c++  java
  • 【DRF视图】

    请结合【DRF序列化】此文献中的数据文件及序列化文件来阅读如下代码.

    DRF视图为我们提供了非常简便的方法——内置了增删改查等一系列的操作.
    我们只需在url中指定对应的方法,视图继承内置方法的类,即可实现两三行代码搞定一个请求.

    @


    我们先看看仿照内置方法实现的

    APIView视图文件:

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.viewsets import ViewSetMixin
    
    
    
    """ ===================== 一层封装 ===================== """
    
    
    class GenericAPIView(APIView):
        queryset = None
        serializer_class = None
    
        def get_queryset(self):
            """用于获取queryset的方法"""
            return self.queryset.all()
    
        def get_serializer(self, *args, **kwargs):
            """用于调用序列化类的方法"""
            return self.serializer_class(*args, **kwargs)
    
    
    class ListModelMixin():
        """用于返回get请求所有数据的数据"""
        def list(self, request):
            queryset = self.get_queryset()  # self调用的方法(get_queryset)是从执行此方法(list)的当前对象的类中开始找
            ser_obj = self.get_serializer(queryset, many=True)  # 原理同上句话
            return Response(ser_obj.data)
    
    
    class CreateModelMixin():
        """用于处理post请求发来的数据"""
        def create(self, request):
            ser_obj = self.get_serializer(data=request.data)
            if ser_obj.is_valid():
                ser_obj.save()
                return Response(ser_obj.validated_data)
            return Response(ser_obj.errors)
    
    
    class RetrieveModelMixin():
        """用于返回get请求查询单条数据方法"""
        def retrieve(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            ser_obj = self.get_serializer(book_obj)
            return Response(ser_obj.data)
    
    
    class UpdateModelMixin():
        """用于处理put请求发来的数据(更新数据)"""
        def update(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
            if ser_obj.is_valid():
                ser_obj.save()
                return Response(ser_obj.validated_data)
            return Response(ser_obj.errors)
    
    
    class DestroyModelMixin():
        """用于删除单条数据"""
        def destroy(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            if book_obj:
                book_obj.delete()
                return Response('')
            return Response('The deleted object does not exist.')
    
    
    
    """ ===================== 二层封装 ===================== """
    
    
    class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
        pass
    
    
    class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        pass
    

    视图文件:

    from .custom_mixin import ListCreateAPIView, RetrieveUpdateDestroyAPIView  # 导入上述的APIView视图文件
    from DRFView import models
    from .serializers import BookSerializer  # 导入自定义的序列化文件
    
    
    class Book(ListCreateAPIView):
        queryset = models.Book.objects.all()  # 坑:这里的queryset只是放到缓存里了,再次取时还需要用.all()方法
        serializer_class = BookSerializer
    
        def get(self, request):
            return self.list(request)
    
        def post(self, request):
            return self.create(request)
    
    
    class BookEdit(RetrieveUpdateDestroyAPIView):
        queryset = models.Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request, id):
            return self.retrieve(request, id)
    
        def put(self, request, id):
            return self.update(request, id)
    
        def delete(self, request, id):
            return self.destroy(request, id)
    

    改进版

    urls.py文件:

    urlpatterns = [
        url(r'^book/$', BookModel.as_view({'get': 'list', 'post': 'create'})),
        url(r'^book/(?P<id>d+)/$', BookModelView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
    ]
    """
    注意as_view的传参:
    as_view({"请求方式": "调用的方法"}, {...})
    指定请求方式调用的方法后,框架会为我们自动执行其方法,无需在CBV中写请求的方法了.
    """
    

    APIView视图文件:

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.viewsets import ViewSetMixin  # 导入DRF封装好的APIView
    
    
    """ ===================== 第一层封装 ===================== """
    
    
    class GenericAPIView(APIView):
        queryset = None
        serializer_class = None
    
        def get_queryset(self):
            """用于获取queryset的方法"""
            return self.queryset.all()
    
        def get_serializer(self, *args, **kwargs):
            """用于调用序列化类的方法"""
            return self.serializer_class(*args, **kwargs)
    
    
    class ListModelMixin():
        """用于返回get请求所有数据的数据"""
        def list(self, request):
            queryset = self.get_queryset()  # self调用的方法(get_queryset)是从执行此方法(list)的当前对象的类中开始找
            ser_obj = self.get_serializer(queryset, many=True)  # 原理同上句话
            return Response(ser_obj.data)
    
    
    class CreateModelMixin():
        """用于处理post请求发来的数据"""
        def create(self, request):
            ser_obj = self.get_serializer(data=request.data)
            if ser_obj.is_valid():
                ser_obj.save()
                return Response(ser_obj.validated_data)
            return Response(ser_obj.errors)
    
    
    class RetrieveModelMixin():
        """用于返回get请求查询单条数据方法"""
        def retrieve(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            ser_obj = self.get_serializer(book_obj)
            return Response(ser_obj.data)
    
    
    class UpdateModelMixin():
        """用于处理put请求发来的数据(更新数据)"""
        def update(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
            if ser_obj.is_valid():
                ser_obj.save()
                return Response(ser_obj.validated_data)
            return Response(ser_obj.errors)
    
    
    class DestroyModelMixin():
        """用于删除单条数据"""
        def destroy(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            if book_obj:
                book_obj.delete()
                return Response('')
            return Response('The deleted object does not exist.')
    
    
    
    """ ===================== 第二层封装 ===================== """
    
    
    class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
        pass
    
    
    class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        pass
    
    
    
    """ ===================== 第三层封装 ===================== """
    
    
    class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
    # ViewSetMixin重写了as_view方法,即可以传参了.
        pass
    

    视图文件:

    from .custom_mixin import ModelViewSet  # 导入上述的APIView视图文件
    from DRFView import models
    from .serializers import BookSerializer  # 导入自定义的序列化文件
    
    
    class BookModel(ModelViewSet):
        queryset = models.Book.objects.all()  
        # 坑:这里的queryset只是放到缓存里了,再次取时还需要用.all()方法
        # queryset是框架能识别的,会把数据放到缓存中,如果该成其它的名字则不会缓存(比如query),即再此取数据时不能加.all()
        serializer_class = BookSerializer
    
    
    class BookModelView(ModelViewSet):
        queryset = models.Book.objects.all()
        serializer_class = BookSerializer
    

    接下来,我们再来看看DRF为我们封装好了的APIView用法。


    开始使用内置视图

    第一步 按照框架的要求写url

    urlpatterns = [
        url(r'^book/$', BookModel.as_view({'get': 'list', 'post': 'create'})),
        # 按照APIView的要求,这里必须写为pk,而不能写id
        url(r'^book/(?P<pk>d+)/$', BookModelView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
    ]
    """
    注意as_view的传参:
    as_view({"请求方式": "调用的方法"}, {...})
    指定请求方式调用的方法后,无需在CBV中写请求的方法了.
    """
    

    第二步 写视图文件

    from DRFView import models
    from .serializers import BookSerializer  # 导入自定义的序列化文件
    from rest_framework.viewsets import ModelViewSet  # 导入DRF封装好的APIView
    
    
    class BookModel(ModelViewSet):
        queryset = models.Book.objects.all()
        serializer_class = BookSerializer
    
    
    class BookModelView(ModelViewSet):
        queryset = models.Book.objects.all()
        serializer_class = BookSerializer
    

    如上步骤,我们的视图只要写两行就可以了.

    关于DRF视图源码解析,推荐参考此文献:https://www.cnblogs.com/GGGG-XXXX/articles/9675911.html

    继承顺序图解:
    在这里插入图片描述



  • 相关阅读:
    mormot2封装tcp
    mormot.net.client.pas
    mormot.net.server.pas
    delphi working with big data databases in Cassandra, Couchbase and MongoDB
    Grijjy.ProtocolBuffers.pas
    Grijjy.Bson.Serialization.pas
    GrijjyFoundation开源框架
    Unidac内存表使用
    传统关系型数据库正在完成华丽的蜕变
    使用arthas 分析java 应用的一个流程总结
  • 原文地址:https://www.cnblogs.com/zyk01/p/10176367.html
Copyright © 2011-2022 走看看