zoukankan      html  css  js  c++  java
  • Django框架(二十三)-- Django rest_framework-视图组件

    一、基本视图

    class PublishView(APIView):
    
        def get(self, request):
            publish_list = Publish.objects.all()
            bs = PublishSerializers(publish_list, many=True)
    
            return JsonResponse(bs.data,safe=False)
    
        def post(self, request):
            # 添加一条数据
            print(request.data)
    
            bs = PublishSerializers(data=request.data)
            if bs.is_valid():
                bs.save()  # 生成记录
                return JsonResponse(bs.data,safe=False)
            else:
    
                return JsonResponse(bs.errors,safe=False)
    
    
    class PublishDetailView(APIView):
        def get(self, request, pk):
            publish_obj = Publish.objects.filter(pk=pk).first()
            bs = PublishSerializers(publish_obj, many=False)
            return JsonResponse(bs.data,safe=False)
    
        def put(self, request, pk):
            publish_obj = Publish.objects.filter(pk=pk).first()
    
            bs = PublishSerializers(data=request.data, instance=publish_obj)
            if bs.is_valid():
                bs.save()  # update
                return JsonResponse(bs.data)
            else:
                return JsonResponse(bs.errors)
    
        def delete(self, request, pk):
            Publish.objects.filter(pk=pk).delete()
    
            return JsonResponse("")

    二、自定义的封装视图

    class Create:
        def create(self,request):
            bs = serializers(data=request.data)
            if bs.is_valid():
                bs.save()  # 生成记录
                return JsonResponse(bs.data,safe=False)
            else:
                return JsonResponse(bs.errors,safe=False)
    
    class List:
        def list(self,request):
            queryset = self.queryset
            bs = self.serializers(queryset, many=True)
            return JsonResponse(bs.data,safe=False)
    
    # 将create和 list方法抽出来,封装起来   
    class PublishView(APIView,List,Create):
        queryset=Publish.objects.all()
        serializers=PublishSerializers
        def get(self, request):
            return self.list(request)
        def post(self, request):
            return self.create(request)
        
    class BookView(APIView,List,Create):
        queryset=Book.objects.all()
        serializers=BookSerializer
        def get(self, request):
            return self.list(request)
        def post(self, request):
            return self.create(request)

    三、利用mixin类和generice类编写视图

    1、使用

    # ListModelMixin 查询所有;  CreateModelMixin:创建数据;  RetrieveModelMixin:查询一条;   UpdateModelMixin:更新数据;  DestroyModelMixin:删除数据
    from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
    from rest_framework.generics import GenericAPIView
    
    class PublishView(GenericAPIView,ListModelMixin,CreateModelMixin):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializers
        def get(self, request):
            # self.list(request),ListModelMixin类中的函数属性
            return self.list(request)
        def post(self, request):
            return self.create(request)
    
    class BookView(GenericAPIView,ListModelMixin,CreateModelMixin):
        queryset = Book.objects.all()
        serializer_class = BookSerializers
        def get(self, request):
            return self.list(request)
        def post(self, request):
            return self.create(request)

    2、源码

    (1)ListModelMixin类
    class ListModelMixin(object):
        def list(self, request, *args, **kwargs):
            # 获取queryset对象,filter_queryset是利用过滤条件过滤
            queryset = self.filter_queryset(self.get_queryset())
            # 分页相关
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
            # 获取序列化对象
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
    (2)self.get_queryset()与self.get_serializer()
    # self.get_queryset()
    # 先自身找,然后类中找,再去父类GenericAPIView中找,找到
    def get_queryset(self):
        # queryset在GenericAPIView设默认值为None,因此要重新定义queryset,指定queryset对象
        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            # 查询所有数据
            queryset = queryset.all()
        return queryset
    # self.get_serializer()
    # 先自身找,然后类中找,再去父类GenericAPIView中找,找到
    def get_serializer(self, *args, **kwargs):
        # get_serializer_class()返回的是serializer_class,默认值为None,所以要重新定义返回的是serializer_class
        serializer_class = self.get_serializer_class()
        kwargs['context'] = self.get_serializer_context()
        return serializer_class(*args, **kwargs)
    (3)CreateModelMixin类下的create
    class CreateModelMixin(object):
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
        
        def perform_create(self, serializer):
            serializer.save()
    (4)UpdateModelMixin类下的update
    class UpdateModelMixin(object):
    
        def update(self, request, *args, **kwargs):
            partial = kwargs.pop('partial', False)
            # get_object 返回的是一个普通对象
            instance = self.get_object()
            serializer = self.get_serializer(instance, data=request.data, partial=partial)
            serializer.is_valid(raise_exception=True)
            self.perform_update(serializer)
    
            if getattr(instance, '_prefetched_objects_cache', None):
    
                instance._prefetched_objects_cache = {}
    
            return Response(serializer.data)
    
        def perform_update(self, serializer):
            serializer.save()
    (5)DestroyModelMixin类下的destroy
    class DestroyModelMixin(object):
    
        def destroy(self, request, *args, **kwargs):
            # get_object 返回的是一个普通对象
            instance = self.get_object()
            self.perform_destroy(instance)
            return Response(status=status.HTTP_204_NO_CONTENT)
    
        def perform_destroy(self, instance):
            instance.delete()
    (6)RetrieveModelMixin类下的retrieve
    class RetrieveModelMixin(object):
        # 
        def retrieve(self, request, *args, **kwargs):
            # get_object 返回的是一个普通对象
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response(serializer.data)

    四、利用generics 下的ListCreateAPIView,RetrieveUpdateDestroyAPIView

    1、使用

    from rest_framework.generics import ListCreateAPIView, ListAPIView, RetrieveUpdateDestroyAPIView
    
    # 继承了ListCreateAPIView类,而ListCreateAPIView又继承了多个类,并且定义了get和post方法,因此,只需要重定义queryset和serializer_class即可
    class PublishView(ListCreateAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializers
    
    class PublishDetailView(RetrieveUpdateDestroyAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializers

    2、源码

    # 继承了多个类,类中的方法也是调用了GenericAPIView类中的list、create函数属性
    class ListCreateAPIView(mixins.ListModelMixin,
                            mixins.CreateModelMixin,
                            GenericAPIView):
    
        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 RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                       mixins.UpdateModelMixin,
                                       mixins.DestroyModelMixin,
                                       GenericAPIView):
    
        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 patch(self, request, *args, **kwargs):
            return self.partial_update(request, *args, **kwargs)
    
        def delete(self, request, *args, **kwargs):
            return self.destroy(request, *args, **kwargs)

    五、使用ModelViewSet(不建议使用)

    1、使用

    # 路由层
    url(r'^publish', views.PublishView.as_view({'get': 'list', 'post': 'create'})),
    url(r'^publish/(?P<pk>d+)', views.PublishView.as_view({'get': 'retrieve', 'put': 'update','delete':'destroy'})),
        
    # 视图层
    
    from rest_framework.views import  APIView
    from rest_framework.viewsets import ModelViewSet
    from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
    class PublishView(ModelViewSet):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializers

    2、源码

    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):
        pass
    
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
        pass
    
    
    # ViewSetMixin是一个魔法类,重写了as_view方法,所以继承该类的时候,一般放前面,否则会调用APIView的as_view方法
    class ViewSetMixin(object):
        """
        This is the magic.
        view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
        """
    
        @classonlymethod
        def as_view(cls, actions=None, **initkwargs):
            cls.name = None
            cls.description = None
            cls.suffix = None
            cls.detail = None
            cls.basename = None
            
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                
                # actions ---> {'get': 'list', 'post': 'create'}
                self.action_map = actions
    
                for method, action in actions.items():
                    handler = getattr(self, action)
                    # 将list方法的地址赋给get,create方法的地址赋给post
                    # 将list绑定给GET,create绑定给POST
                    setattr(self, method, handler)
    
                if hasattr(self, 'get') and not hasattr(self, 'head'):
                    self.head = self.get
    
                self.request = request
                self.args = args
                self.kwargs = kwargs
    
                # And continue as usual
                return self.dispatch(request, *args, **kwargs)
    
            # take name and docstring from class
            update_wrapper(view, cls, updated=())
    
            update_wrapper(view, cls.dispatch, assigned=())
    
            view.cls = cls
            view.initkwargs = initkwargs
            view.actions = actions
            return csrf_exempt(view)    

    六、强调:ViewSetMixin魔法类

    • ViewSetMixin类重写了as_view方法,因此为了调用它的as_view方法,在继承的时候,要写在APIView前面
    class TestAll(ViewSetMixin,APIView):
        pass
    • ViewSetMixin 类可以实现全部视图函数写在一个类中
    # 路由层
    [
        url(r'^test1/$', views.TestAll.as_view({'get': 'test'})),  # 将test视图函数赋给get
        url(r'^test2/$', views.TestAll.as_view({'get': 'test2'})),
        url(r'^test3/$', views.TestAll.as_view({'get': 'test3'}))
    ]
    
    # 视图层
    class TestAll(ViewSetMixin,APIView):
        def test(self,request):
            return HttpResponse('test')
    
        def test2(self, request):
            return HttpResponse('test2')
    
        def test3(self, request):
            return HttpResponse('test3')
  • 相关阅读:
    Factorial Trailing Zeroes
    Convert Integer A to Integer B
    函数防抖、函数节流
    localstorage sessionstorage和cookie的区别
    element中表格中的表头与表格内容边框错位的解决方法
    解决Minio生成图片文件的分享链接无法正常下载的问题
    gin编写后端API的使用技巧
    YOLOV5源码解读-export.py网络结构、配置文件
    《三、YOLOV3细节原理全解析》
    《二、YOLOV2细节原理全解析》
  • 原文地址:https://www.cnblogs.com/zhangbingsheng/p/10111718.html
Copyright © 2011-2022 走看看