• Django Rest Framework----ModelViewSet视图 ModelViewSet源码分析


    一、视图类

    #bookview是一个视图类,继承自ModelViewSet
    class BookView(ModelViewSet):
        throttle_classes = [VisitThrottle2]
        queryset = models.Book.objects.all()
        serializer_class = BookModelSerializer

    ModelViewSet

    ModelViewSet:
            class ModelViewSet(mixins.CreateModelMixin,    # 实现了post添加逻辑
                       mixins.RetrieveModelMixin,          # 实现了获取具体某一本书的逻辑
                       mixins.UpdateModelMixin,            # 实现了put编辑的逻辑
                       mixins.DestroyModelMixin,           # 实现了删除一本书的逻辑
                       mixins.ListModelMixin,              # 实现了获取所有书的逻辑
                       GenericViewSet):                    # 提供了APIView和dispatch的功能
    ....
    由于ModelViewSet继承了多个混合类和通用视图类,所以ModelViewSet提供了.list(),.retrieve(), .create(),.update(),.partial_update(),和.destroy()
    因为ModelViewSet继承了GenericViewSet,所以BookView需要提供queryset和serializer_class属性

    二、执行流程

    1. url:

    url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})),
    url(r'books/(?P<pk>d+)/$',views.BookDetailView.as_view({'get': 'retrieve',
                                                                 'put':'update',
                                                                 'delete':'destroy'})),

    当django启动的时候,会执行view.BookView.as_view()方法:由于as_view()是从ViewSetMixin中继承而来的,所以url会变为:

    url(r'books/$',ViewSetMixin.view),
    url(r'books/(?P<pk>d+)/$',ViewSetMixin.view),

    2.当用户访问books/的时候,会调用执行ViewSetMixin.view并传入request

    class ViewSetMixin(object):
             """
                他是一个魔法方法
                重写`.as_view()‘,以便它接受一个’actions‘关键字,
                该关键字执行HTTP方法到资源上的操作的绑定。
                例如,要创建一个将“GET”和“POST”方法绑定到“List”和“Create”操作的具体视图.
                view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
            """
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                self.action_map = actions
    
                # {'get':'list','post':'create'}
                # {'get': 'retrieve','put':'update','delete':'destroy'}
    
                for method, action in actions.items():
                    # self:ModelViewSet继承的每一个类 action是list create等方法。
                    # handler是每一个具体的函数名
                    handler = getattr(self, action)
                    #为属性赋值, self.get = list, self.get = retrieve
                    # 当get请求的时候,真正会执行的是list/retrieve方法
                    setattr(self, method, handler)
    
                # 进行分发,由于以上几个类都没有实现该方法,所以dispatch()执行的是APIView的dispatch()
                return self.dispatch(request, *args, **kwargs)

    3.ViewSetMixin的view主要是把mixins中的list()、create()、retrieve()、等绑定给BookView的get()、post()等

    4.dispatch()

    def dispatch(self, request, *args, **kwargs):
    
                try:
                    self.initial(request, *args, **kwargs)
    
                    # get、put、post等请求方法,去list、create、update等,去执行
                    if request.method.lower() in self.http_method_names:
    
                        # 这里的self是ViewSetMixin。
                        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

    当客户端请求方式是get的时候,执行BookView的get()方法,实际上是执行的list().因为在ViewSetMixin.view()中,获取minx下的list、create等函数地址,通过settattr()的方式绑给了BookView实例对象

    三、总结:

    django启动******
    
            url(r'books/$',views.BookView.as_view({'get':'list','post':'create'})),   1
                url(r'books/$',ViewSetMixin.view)),    2
    
        一旦用户访问******
    
            books  get请求
    
             def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                {'get':'list','post':'create'}
    
                for method, action in actions.items():
    
                    handler = getattr(self, action)
                    #给BookView设置一个属性  BookView.get = ListModelMixin.list
                    setattr(self, method, handler)
    
                return self.dispatch(request, *args, **kwargs)
    
             url(r'books/$',APIView.dispatch)),  3
    
             if get in self.http_method_names:
    
                # 这里的self是ViewSetMixin。
                handler = getattr(self, 'get'),  --> BookView.get ---> 实际上执行的是 ListModelMixin.list
                                  self.http_method_not_allowed)
    
    
             handler返回什么,dispatch返回什么,view返回什么,用户看到什么
  • 相关阅读:
    Ubuntu 14.04还能看的过去的字体
    Android 65536问题
    Ubuntu 下如何设置 Java 环境变量
    rime 必知必會
    基于ParserCombinator的正则表达式引擎
    Spring源码分析——Configuration配置类解析流程
    Spring源码分析——AnnotationConfigApplicationContext组件注册流程
    在SpringBoot中实现策略模式
    ByxOrm——模仿MyBatis的轻量级ORM框架
    ByxContainerAnnotation——基于注解的轻量级IOC容器
  • 原文地址:https://www.cnblogs.com/weihengblog/p/9212100.html
Copyright © 2020-2023  润新知