美文网首页
DRF之视图组

DRF之视图组

作者: 清风徐来_简 | 来源:发表于2019-05-26 16:54 被阅读0次
  • 先大概看一下这几个 视图类 的关系

    视图组.jpg
  • 使用APIView,定义方法

    views中:
    from rest_framework.views import APIView
    
    class BookView(APIView):
        # 查看所有
        def get(self, request):
            pass
        # 添加单条
        def post(self, request):
           pass
    class SBookView(APIView):
        # 查看单条
        def get(self, request, id):
           pass
        # 更改单条
        def put(self, request, id):
            pass
        # 删除单条
        def delete(self, request, id):
            pass
    
    对应的url:
       url(r'^book/$', views.BookView.as_view()),  # 必须加上结尾符,否则匹配不到下面
       url(r'^book/(\d+)/', views.SBookView.as_view()),
    
  • 进一步封装

    views1中:
    from rest_framework import generics
    # 处理增删改查查的五个类,每个类里都有各自的处理方法
    from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \
      RetrieveModelMixin
    
    from app01.models import Publish
    
    class PublishSerializer(serializers.ModelSerializer):
        class Meta:
            model = Publish
            fields = '__all__'
    
    
    class PublishView(ListModelMixin, CreateModelMixin, generics.GenericAPIView):  # 【APIView由这个类里继承】
        queryset = Publish.objects.all()  # 【这两个变量必须交这个名字,因为继承类里面要拿这个变量去处理】
        serializer_class = PublishSerializer
    
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)  # 在ListModelMixin里有这个方法
    
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs)  # 在CreateModelMixin里有这个方法
      
    
    class SPublishView(UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, generics.GenericAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
    
        def get(self,request,*args,**kwargs):
            return self.retrieve(request,*args,**kwargs)  # 在 RetrieveModelMixin里有这个方法
    
        def put(self,request,*args,**kwargs):
            return self.update(request,*args,**kwargs)  # 在 UpdateModelMixin里有这个方法
    
        def delete(self,request,*args,**kwargs):
            return self.destroy(request,*args,**kwargs)  # 在 DestroyModelMixin里有这个方法
    
    对应的url:
        url(r'^publishes/$',views1.PublishView.as_view()),
        url(r'^publishes/(?P<pk>\d+)/', views1.SPublishView.as_view()),  # 参数必须以此命名,因为函数处理时就接收这个参数
    
  • 再一步封装

    views2中:
    from rest_framework import generics
    from app01.models import Author
    
    class AuthorSerializer(serializers.ModelSerializer):
        class Meta:
            model = Author
            fields = '__all__'
    
    # 简直太省了,把get和post等方法都封装进了类里。
    class AuthorsView(generics.ListCreateAPIView):  # 这个类里提供get,post两个方法
        queryset = Author.objects.all()
        serializer_class = AuthorSerializer
    
    
    class SAuthorsView(generics.RetrieveUpdateDestroyAPIView):  # 这个类提供了get/1,put/1,delete/1。3个方法
        queryset = Author.objects.all()
        serializer_class = AuthorSerializer
    # 上面两个类对之前的类又进行了封装
    
    对应的url:
        url(r'^authors/$',views2.AuthorsView.as_view()),
        url(r'^authors/(?P<pk>\d+)/', views2.SAuthorsView.as_view()),
    
  • 终极封装

    views3中:
    from rest_framework.viewsets import ModelViewSet
    
    from app01.models import Author
    from app01.serializer import AuthorSerializer
    
    class AuthorsView(ModelViewSet):
        queryset = Author.objects.all()
        serializer_class = AuthorSerializer
    
    对应的url:
        url(r'^authorsss/$',views3.AuthorsView.as_view({'get':'list','post':'create'})),
        url(r'^authorsss/(?P<pk>\d+)/',views3.AuthorsView.as_view({'get':'retrieve','delete':'destroy','put':'update'}))
        # ↑上面的as_view中的参数必须以此命名
    

封装的越深,约束性越大,功能的扩展性就越差,所以最后可根据不同的业务逻辑去使用不同的方法。

  • ModelViewSet源码流程
    • 1,继承ModelViewSet

      class AuthorsView(ModelViewSet):
          queryset = Author.objects.all()
          serializer_class = AuthorSerializer
      
    • 2,先进去,看看里面的结构,继承了哪些类

      class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
          """
          A viewset that provides default `create()`, `retrieve()`, `update()`,
          `partial_update()`, `destroy()` and `list()` actions.
          """
          pass
      
    • 3,前5个类,分别封装了几种不同的操作方法,最后一个GenericViewSet功能强大

      class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
          """
          The GenericViewSet class does not provide any actions by default,
          but does include the base set of generic view behavior, such as
          the `get_object` and `get_queryset` methods.
          """
          pass
      
    • 4,左边的ViewSetMixin,有as_view方法,将方法赋给其对象

      class ViewSetMixin(object):
      # 如果使用ModelViewSet,则执行的as_view就是ViewSetMixin中的as_view方法。
          @classonlymethod
          def as_view(cls, actions=None, **initkwargs):
              # 如果没有定义,就报错,所以必须那样写。
              if not actions:
                  raise TypeError("The `actions` argument must be provided when "
                                  "calling `.as_view()` on a ViewSet. For example "
                                  "`.as_view({'get': 'list'})`")
      
              def view(request, *args, **kwargs): 
                  self = cls(**initkwargs)
                  self.action_map = actions
      
                  for method, action in actions.items(): # 核心代码:把参数里面的键值对,以self.method = ...的形式,变成了self的属性
                      handler = getattr(self, action)
                      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
      
                  return self.dispatch(request, *args, **kwargs)
      
              return csrf_exempt(view)
      
    • 5,右边的generics.GenericAPIView继承了APIView

      class GenericAPIView(views.APIView):
      
    • 6,APIView中有dispatch方法

      def dispatch(self, request, *args, **kwargs):
          self.args = args
          self.kwargs = kwargs  # 路由中传的命名参数 
          # 1,重新封装request对象
          request = self.initialize_request(request, *args, **kwargs)
          self.request = request
          self.headers = self.default_response_headers  # deprecate?
      
          try: 
              # 2,认证,权限,频率
              self.initial(request, *args, **kwargs)
              
              # 【用字符串,反射self里面对应的方法,此步之后就有了self.get/self.post】
              # Get the appropriate handler method
              if request.method.lower() in self.http_method_names:
                  handler = getattr(self, request.method.lower(),
                                    self.http_method_not_allowed) # 【如果没有找到,就走这一个】
              else:
                  handler = self.http_method_not_allowed
      
              response = handler(request, *args, **kwargs)
      
          except Exception as exc:
              response = self.handle_exception(exc)
      
          self.response = self.finalize_response(request, response, *args, **kwargs)
          return self.response
      

相关文章

  • DRF之视图组

    先大概看一下这几个 视图类 的关系视图组.jpg 使用APIView,定义方法views中:from rest_f...

  • DRF之视图

    DRF框架包含序列化器,视图以及URL视图,三者密不可分,因此本篇聊的是视图部分。在django中rest_fra...

  • DRF使用记录(三) - 视图

    drf使用记录(三) - 视图 视图之前还忘记了点啥 模型类序列化器 DRF为我们提供了ModelSerializ...

  • 七、DRF之视图

    写在前面-->视图回顾: Django视图的使用 Django的函数视图:注意这里的 request 和 resp...

  • 【DRF】快速上手 View APIView Viewset

    简介 APIView 和 Viewset 是 DRF 中引入的视图类,Viewset 对 DRF 自身提供的 AP...

  • Django基础:drf 源码视图解析

    Django 与drf 源码视图解析 一.原生Django CBV 源码分析:View 二.drf CBV 源码分...

  • django rest framework 中的三种视图写法

    一、基本视图类 (APIView/@api_view) 1、类基础视图(APIView) DRF不同于django...

  • drf 的 cbv View

    drf 也可以使用 cbv 这种视图,不过其对 Django 的 view 做了一些封装。drf 最底层的 vie...

  • DRF的视图

    这些功能可以移植到其他的任何地方,其他项目大体上也是有是这种增加删改查的需求,说一Django吧这些功能封装到类里...

  • Django drf 视图

    原来 现在 GenericAPIView(和APIView)差不多 GenericViewSet(路由系统有所变化...

网友评论

      本文标题:DRF之视图组

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