zoukankan      html  css  js  c++  java
  • drf视图

    不使用drf视图

    #在下面的这些代码中,存在很多代码重复
    from rest_framework.views import APIView
    from app01.models import *
    from app01.mySer import *
    from django.http import JsonResponse
    
    class PublishView(APIView):
    
        def get(self, request):     #获取所有数据
            publish_list = Publish.objects.all()
            bs = PublishSerializers(publish_list, many=True)    #PublishSerializers自己写的序列化
    
            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("")
    View Code

    还是不使用drf,但进行了封装

    #自己写两个类,把重复代码抽出来
    class List:    #列表,拿多条
        #把获取多条的get抽过来
        def list(self):              
            publish_list = Publish.objects.all()
            bs = PublishSerializers(publish_list, many=True)  # PublishSerializers自己写的序列化
    
            return JsonResponse(bs.data, safe=False)
    
    
    class Create:
      #把post方法抽过来
        def create(self,request):      
            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 PublishView(APIView,List,Create):
    
        def get(self, request):  # 获取所有数据
            return self.list(request)      #当请求来到这时,在当前找不到list方法,然后去父类找,执行,并拿到结果
    
        def post(self, request):
            return self.create(request)#同理,请求来了,去父类中找create方法
    
    ---------------------------------------------------
    #但是
    #上面这种方式只能对应Publish表,PublishSerializers序列化组件,写死了
    class BookhView(APIView, List, Create)    
                                              #
        def get(self, request):
            return self.list(request)
    
        def post(self, request):
            return self.create(request)
    不够精简的封装
    #把写死的地方,通过传值写活
    
    class List:    #列表,拿多条
        def list(self):    #把获取多条的get抽过来
            # publish_list = Publish.objects.all()     #原来的方式
            # bs = PublishSerializers(publish_list, many=True
    
            queryset = self.queryset               #把原本写死的东西写活
            bs = self.serializers(queryset, many=True)  #把原本写死的东西写活
    
            return JsonResponse(bs.data, safe=False)
    
    class Create:
        def create(self,request):      #把post方法抽过来
            print(request.data)
            # bs = PublishSerializers(data=request.data)
            bs = self.serializers(data=request.data)         #把原本写死的东西写活
            if bs.is_valid():
                bs.save()  # 生成记录
                return JsonResponse(bs.data, safe=False)
            else:
                return JsonResponse(bs.errors, safe=False)
    
    -------------------------------------------
    #使用
    class PublishView(APIView,List,Create):      #前边自己写的两个类,是怎么处理,一定要与这里的怎么用区分开,条理清晰
        queryset= Publish.objects.all()         #需要用哪个模型表,就传给queryset
        serializers=PublishSerializers          #需要用哪个序列化组件,就把谁赋给serializers
        def get(self, request):  # 获取所有数据
            return self.list(request)      #当请求来到这时,在当前找不到list方法,然后去父类找,执行,并拿到结果
    
        def post(self, request):
                return self.create(request)#同理,请求来了,去父类中找create方法
    
    
    class BookhView(APIView, List, Create)     #此时就比较方便了,再来多少都行,只需要把模型表
        queryset= Book.objects.all()         #需要用哪个模型表,就传给queryset
        serializers=BookSerializers          #需要用哪个序列化组件,就把谁赋给serializers
        def get(self, request):
            return self.list(request)
    
        def post(self, request):
            return self.create(request)
    升级版封装

    使用drf封装的类

    先看源码(拿两个典型的,其他的类似)

    #GenericAPIView它继承了APIView,只不过添加了一些方法
    其他几个类要基于它使用,
    class GenericAPIView(views.APIView):
        queryset = None
        serializer_class = None
    
        lookup_field = 'pk'
        lookup_url_kwarg = None
    
        filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
    
        pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
    
        def get_queryset(self):
        def get_object(self):
        def get_serializer(self, *args, **kwargs):
        def get_serializer_class(self)     
        def get_serializer_context(self)
        def filter_queryset(self, queryset)
    GenericAPIView源码
    class ListModelMixin(object):
    
        def list(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())  #类似于自己写的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)
    
    
    queryset     #这些都需要去GenericAPIView中
    get_queryset
    filter_queryset
    ListModelMixin源码

    使用

    #GenericAPIView继承了APIView,只不过添加了几个方法
    
    #拿多个
    class PublishView(GenericAPIView,ListModelMixin,CreateModelMixin):
        queryset= Publish.objects.all()
        serializer_class=PublishSerializers
        def get(self, request):
            return self.list(request)   
    
    #请求来到这里,list方法,自己,没有,去父类,在ListModelMixin中找到,父类中需要的
    filter_queryset,paginate_queryset,get_serializer先来自己这找,自己这没有,去父类中,在GenericAPIView中找到
    
        def post(self, request):      #添加用CreateModelMixin
            return self.create(request)   #同样道理,create去父类中找,父类中需要的其他参数,去另外父类中找
    
    
    ---------------------------------------------------------
    #拿一个的方法,道理同上
    from rest_framework.mixins import ListModelMixin,RetrieveModelMixin,RetrieveModelMixin,DestroyModelMixin
    from rest_framework.generics import GenericAPIView
    
    
    class PublishDetailView(APIView):
        queryset= Publish.objects.all()
        serializer_class=PublishSerializers
        def get(self, request,pk):               #RetrieveModelMixin
            return self.retrieve(self, request, pk)
    
    
        def post(self, request,pk):            #RetrieveModelMixin
            return self.update(request,pk)
    
    
        def delete(self, request, pk):       #DestroyModelMixin
            return self.destroy(request,pk)
    
    
    
    
    ------------------------------------------
    #这种方法仍然存在重复代码,取多个,取一个都要指定
        queryset= Publish.objects.all()
        serializer_class=PublishSerializers
    View Code

    使用drf升级版(最终版)

    # 上面发现仍有重复代码
    # queryset = Publish.objects.all()
    # serializers = PublishSerializers
    from rest_framework.viewsets import ModelViewSet
    class PublishDetailView(ModelViewSet):    #只需要写这一个,5个接口都有了
        queryset= Publish.objects.all()
        serializer_class=PublishSerializers
    
    
    #不过路由需要传参
        url(r'^books/$', views.Book.as_view({'get': 'list', 'post': 'create'})),
        url(r'^books/(?P<pk>d+)/$',views.Book.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),

     这种情况不建议使用,一般自己写类,继承魔法类,自己在类中实现功能

     

    #1、ModelViewSet
    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,           #前四个已经了解
                       GenericViewSet):      #重点读这个源码
    
    
    2、#来到GenericViewSet
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    
        pass     #源码的pass
    #它继承了ViewSetMixin
    
    
    
    
    #3、来看ViewSetMixin
    #url(r'^books/$', views.Book.as_view({'get': 'list', 'post': 'create'})),
    #url(r'^books/(?P<pk>d+)/$',views.Book.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
    
    
    class ViewSetMixin(object):    #路由的参数给actions
        def as_view(cls, actions=None, **initkwargs):
    
            def view(request, *args, **kwargs):  #重写了view方法
                  #{'get': 'list', 'post': 'create'}
                 #如果method=get  ,action = list
                for method, action in actions.items():    #解压取值
                    #handler 就是list的内存地址
                    handler = getattr(self, action)
                     #把list的内存地址,赋值给了get,    
                    setattr(self, method, handler)
    那么如果是{'get': 'retrieve'},,直接把retrieve赋值给get
    ViewSetMixin魔法类
    #可以实现在一个类中,路由地址不一样
    
    
    
    
    from rest_framework.viewsets import ViewSetMixin
    #注意前后顺序,ViewSetMixin一定放在前边,为了执行它的as_view方法
    class TestAll(ViewSetMixin,APIView):
        def text1(self,request):
            return HttpResponse('text1')
    
        def text2(self,request):
            return HttpResponse('text2')
    
        def text3(self,request):
            return HttpResponse('text3')
    
        def text4(self,request):
            return HttpResponse('text4')
    
    
    ------------------------------------------------
    urls
        url(r'^text1/$', views.TestAll.as_view({'get': 'tet1'})),
        url(r'^text1/$', views.TestAll.as_view({'get': 'tet2'})),
        url(r'^text1/$', views.TestAll.as_view({'get': 'tet3'})),
        url(r'^text1/$', views.TestAll.as_view({'get': 'tet4'})),
    魔法类用法
  • 相关阅读:
    [转]Android输入法框的梳理
    [转]Android中OptionMenu的使用
    [转] Android把view的画面转换为bitmap
    Health Level Seven International (HL7)
    [转]andriod的apk文件相关的编译反编译工具
    [转]Android优秀开源项目收集
    而立之年 独立自主
    [转]Android模拟键盘和键盘监听的一些调研
    [转] linux中如何能在DDMS中打开真机中的数据库
    [转]关于使用SurfaceFligner进行绘图的具体实现方法
  • 原文地址:https://www.cnblogs.com/pdun/p/11257059.html
Copyright © 2011-2022 走看看