• importlib的使用、9个视图子类、视图集、drf之路由、drf之请求响应回顾、GenericViewSet相关流程图


    1 drf之请求响应回顾
    2 9个视图子类





    1 drf之请求响应回顾

    # 1 drf请求
    	-请求对象:data,query_params,其他跟之前一样,FILES
        -默认:支持三种编码
        	-局部配置:视图类中
            	-from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
            	-parser_classes = [JSONParser]
                
            -全局配置:
            REST_FRAMEWORK = {
            'DEFAULT_PARSER_CLASSES': [
                'rest_framework.parsers.JSONParser',
                'rest_framework.parsers.FormParser',
                'rest_framework.parsers.MultiPartParser'
            	],
    		}
            
            -全局使用了,局部再换---》视图类改即可
            
    # 2 drf响应
    	-Response  ---》一定继承了django原生的HTTPResponse
          -data:字典,列表,字符串,空赋值给它---》http响应体中
          -status:http响应状态码  from rest_framework import status
          -headers:响应头
             res=HttpResponse()  res=render()   res=redirect()  res=JsonResponse()四件套之一
                res['name']='lin'  # 放到响应头中
                return res
         -响应编码格式---》一般不动 
    
    # 3 两个视图基类
    	-APIView---》写了5个接口
        -GenericAPIView 继承自APIView---》以后跟数据库打交道和要序列化就用它
        	### 重要属性### 
        	-queryset:以后放所有某个表查询出的数据
            -serializer_class:要序列化的类
            
            ### 重要方法###
            -get_queryset  :要序列化的所有数据,qs对象
            -get_serializer :序列化类
            -get_object  :修改,查询,删除 的单条
            
            
    # 4 5个视图扩展类
        RetrieveModelMixin, 
        CreateModelMixin, 
        DestroyModelMixin, 
        ListModelMixin, 
        UpdateModelMixin
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    2 9个视图子类

    from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView
    from rest_framework.generics import RetrieveAPIView, DestroyAPIView, UpdateAPIView
    from rest_framework.generics import RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
    
    # 以后想写5个接口中的某一个或某几个或所有,只需要选择继承不同的类即可,类中只需要配置两个类属性
    	queryset = Publish.objects.all()
        serializer_class = PublishSerializer
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1 视图类

    #1 想写  publish: 查询所有,查询单条,修改一条,新增一条,删除一条的接口
    class PublishView(ListCreateAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
    
    
    class PublishDetailView(RetrieveUpdateDestroyAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
    
    #2 想写  publish: 查询单条,新增一条,的接口--->使用9个视图子类编写
    class PublishView(CreateAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
    
    
    class PublishDetailView(RetrieveAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
    
    #3 想写  publish: 查询单条,新增一条,的接口--->使用5个视图扩展类+GenericAPIView
    class PublishView(GenericAPIView,CreateModelMixin):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
        def post(self,request,*args,**kwargs):
            return self.create(request,*args,**kwargs)
    class PublishDetailView(GenericAPIView,RetrieveModelMixin):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
        def get(self,request,*args,**kwargs):
            return self.retrieve(request,*args,**kwargs)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    2 路由

    path('publish/', PublishView.as_view()),
    path('publish/', PublishView.as_view()),
    
    • 1
    • 2

    三 视图集

    1 ModelViewSet

    # 1 只要视图类继承了它,路由写法改一下,5个接口都有了
    from rest_framework.viewsets import ModelViewSet
    class PublishView(ModelViewSet):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
        
        
    path('publish/', PublishView.as_view({'get':'list','post':'create'})),
    path('publish/', PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.1 ModelViewSet源码分析

    # 有查询所有接口
    	-get--list----》拿到所有数据,序列化--返回
        
    # 新增一条
    	-post---create---》之前咱们写的新增的代码一样的
        
        
        
    # 为什么get 就变成了list
    # 为什么post 就变成了create
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2 ViewSetMixin

    # 没见过
    # ViewSetMixin 决定了,以后路由写法就变了
    	-path('publish/', PublishView.as_view({'get':'list','post':'create'}))
        -path('publish/', PublishView.as_view({'get':'lqz'}))
        
    # 源码分析
    	-class GenericViewSet(ViewSetMixin, generics.GenericAPIView):ViewSetMixin必须放前面--》保证执行的as_view是ViewSetMixin的
            
        -请求来了,路由匹配成功---》执行ViewSetMixin的as_view内的view(request)
            def view(request, *args, **kwargs):
                self = cls(**initkwargs) # 类实例化得到对象--》self是谁的对象?PublishView
                self.action_map = actions # {'get':'list','post':'create'}
                # method:get
                # action: list
                for method, action in actions.items():
                    # list 方法
                    handler = getattr(self, action) #PublishView对象中反射list,拿到了
                    # 反射设置值
                    #setattr(PublishView视图类的对象,get,list 方法)
                    # PublishView视图类的对象中就会有一个get方法,就是list
                    setattr(self, method, handler)
                return self.dispatch(request, *args, **kwargs)
    # 总结:
    	-路由中这样配置:PublishView.as_view({'get':'list','post':'create'})
        -以后get请求过来,本质执行的就是视图类中的list方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.1 以后视图类中方法名可以随意命名,只要路由做好映射

    # 继承的类是:只要继承ViewSetMixin ,就能视图类中方法任意命名,路由写法变化
    
    • 1

    3 ReadOnlyModelViewSet

    # 以后写的接口,只想有 获取单条和获取所有,继承它
    
    • 1

    4 视图层中类的总结

    # 1 两个视图基类
    	-APIView和GenericAPIView
        -APIView的执行流程:包装了新的  处理了csrfrequeset,执行了3大认证,处理全局异常
        -GenericAPIView:要做序列化,要跟数据库打交道,就直接继承它即可
        	-queryset
            -serializer_class
            
            -get_object
            -get_queryset
            -get_serializer
            
            
    # 2 5个视图扩展类(不是视图类),需要GenericAPIView才能用
    	-快速使用5个接口
        -某几个接口:查询单条,新增一条,的接口--->使用5个视图扩展类+GenericAPIView
        	class PublishView(GenericAPIView,CreateModelMixin)
            	queryset=Publish.objects.all()
            	serializer_class=序列化类
                def post(self,request)
                	return self.create(request)
            class PublishDetailView(GenericAPIView,RetrieveModelMixin)
            	queryset=Publish.objects.all()
            	serializer_class=序列化类
                def get(self,request)
                	return self.retrieve(request)
                
                
    # 3 9个视图子类(继承GenericAPIView+5个视图扩展类的组合)
    	ListAPIView, CreateAPIView  
        ListCreateAPIView
        
    	RetrieveAPIView, DestroyAPIView, UpdateAPIView
    	RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
        
        
    # 4 视图集
    	-ModelViewSet:
        	-ViewSetMixin+GenericAPIView+5个视图扩展类
            -GenericViewSet+5个视图扩展类
            
        -ViewSetMixin源码:路由做映射的配置,以后视图类中方法可以随便命名
        -Viewset:ViewSetMixin+APIView---》不需要序列化,路由写法变了
        -GenericViewSet:ViewSetMixin+GenericAPIView--》需要序列化,需要用数据库,路由写法变化
        -ReadOnlyModelViewSet:list和retrieve
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    四 drf之路由

    # 之前路由写法:
    	path('books/', BookView.as_view())
        
    # 以后一旦继承了ViewSetMixin,就变成了path('publish/', PublishView.as_view({'get': 'list', 'post': 'create'}))
    
    # 这样写起来,做映射,可能有些麻烦,于是drf,帮咱们封装了两个路由类---》可以帮助咱们快速生成之前咱们写的映射关系
    
    
    ###### 必须是继承ViewSetMixin+APIView及其子类才能自动生成  SimpleRouter  DefaultRouter
    
    ## 自动生成路由:自动映射如下:
    {'get': 'list', 'post': 'create'}
    {'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}
    
    
    ## 其他的-->视图类中有别的方法,我们想做映射,需要使用装饰器
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    使用方式

    # 大前提:必须是继承ViewSetMixin+APIView及其子类才能自动生成
    ####使用步骤
    # urls.py中
    #### 1 导入路由类
    from rest_framework.routers import SimpleRouter, DefaultRouter
    #### 2 类实例化得到对象
    router = SimpleRouter()
    #### 3 自动生成路由,调用对象的某个方法,完成跟视图类的对应关系,映射路由
    router.register('publish', PublishView, 'publish')
    # router.register('books', BookView, 'books') #  后期可以注册更多
    router.register('user',UserView,'user')
    ##### 4 把自动生成的路由,加到总路由中
    urlpatterns = urlpatterns + router.urls  # 两个列表直接相加
    
    ### 第四步可以这样写
    	path('api/v1/', include(router.urls)),   # http://127.0.0.1:8008/api/v1/user/register/--->post
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    1 SimpleRouter, DefaultRouter

    SimpleRouter, DefaultRouter区别
    	-DefaultRouter生成的路径多一个根路径 api-root
        -DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据
    以后就用:SimpleRouter就可以
    
    • 1
    • 2
    • 3
    • 4

    2 action装饰器

    # 作用:为视图类中的方法做路径的映射
    	-这些方法需要排除5个 :create,list,destroy,update,retrieve
        
    # 使用方式
        @action(methods=['POST'],detail=False)
        def register(self, request):
            return Response('register')
    # 自动生成:
    	http://127.0.0.1:8008/user/register/---->post--->就会执行register
    # action参数
    	-methods请求方式,可以写多个
        -detail:路径中是否带id号  
        	http://127.0.0.1:8008/user/register/    # detail=False
            http://127.0.0.1:8008/user/4/register/  # detail=True
    
    
    
    *********************** 代码展示 ***********************************
    -1.路由
    from django.contrib import admin
    from django.urls import path
    from app01.views import UserView
    
    # 1.导入路由类
    from rest_framework.routers import SimpleRouter, DefaultRouter
    # 2.类实例化得到对象
    router = SimpleRouter()
    # 3.自动生成路由,调用对象的某个方法,完成跟视图类的对应关系,映射路由
    router.register('user', UserView, 'user')
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        # 访问 login/路径  post请求就会执行UserView中的register方法
        path('register/', UserView.as_view({'post': 'register'})),
    
    ]
    
    urlpatterns += router.urls
    
    
    
    -2.视图函数
    from rest_framework.decorators import action
    
    
    class UserView(GenericViewSet):
        # http://127.0.0.1:8000/user/register/ ----> post -----> 就是执行 register
        # url_path 是路径后面的名字, 如果不写,就以方法名为路径
    
        # @action(methods=['POST'], detail=False, url_path='reg')
        # methods 请求方式
        # detail 是否带id
    
        # @action(methods=['POST'], detail=False)
        @action(methods=['POST'], detail=True)
        # def register(self, request):
        # http://127.0.0.1:8000/user/2/register/
        def register(self, request, pk):
            print(pk)
            # self.get_queryset()
            return Response('register')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    3 以后继承ModelViewSet也可也能会重写好多方法

    #### 重写list
    class PublishView(ModelViewSet):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
        def list(self, request, *args, **kwargs):  # 以后可能会重写list,做自己的定制
            res=super().list(request, *args, **kwargs)
    
            return Response({'code':100,'msg':'成功','result':res.data})
        
        
    ### 重写get_serializer_class
    def get_serializer_class(self):  # 是GenericAPIView类中的方法,返回什么,以后就以哪个序列化类继续操作
        print(self.action)
        if self.request.method=='POST':
            return WritePublishSerializer
        else:
            return self.serializer_class
    
        
    ### 重写perform_create
    def perform_create(self, serializer):
        serializer.save()
    
    
    ### 序列化使用PublishSerializer,反序列化使用 WritePublishSerializer   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    4 视图类的对象中的action参数

    print(self.action)  
    # 视图类的对象中有个action属性---》它是当次请求执行的方法名的字符串
    
    # 通过action可以限制视图类中某个方法使用的序列化类是哪个
    
    • 1
    • 2
    • 3
    • 4

    importlib的使用

    `importlib` 是 Python 标准库中的一个模块,它提供了一种动态导入模块和获取模块信息的方式,
    允许你在运行时加载、导入和使用 Python 模块。这对于编写可扩展、灵活的代码和插件系统非常有用。
    
    以下是一些 `importlib` 模块的常见用法示例:
    
    1. **动态导入模块**import importlib
    
       # 动态导入模块
       module_name = "my_module"
       my_module = importlib.import_module(module_name)
    
       # 使用动态导入的模块
       result = my_module.my_function()
    
    2. **从模块中导入对象**import importlib
    
       # 动态导入模块
       module_name = "my_module"
       my_module = importlib.import_module(module_name)
    
       # 从模块中导入对象
       my_function = getattr(my_module, "my_function")
    
       # 使用导入的对象
       result = my_function()
    
    3. **重新加载模块**import importlib
    
       # 动态导入模块
       module_name = "my_module"
       my_module = importlib.import_module(module_name)
    
       # 重新加载模块
       my_module = importlib.reload(my_module)
    
    4. **获取模块的文件路径**import importlib
    
       # 动态导入模块
       module_name = "my_module"
       my_module = importlib.import_module(module_name)
    
       # 获取模块的文件路径
       module_path = my_module.__file__
    
    
    这些示例演示了如何使用 `importlib` 动态导入模块、从模块中导入对象、
    重新加载模块以及获取模块的文件路径。
    这些功能可以用于构建插件系统、模块化应用程序和动态加载模块的需求。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    五、GenericViewSet相关流程图

    1.GenericViewSet继承流程图

    在这里插入图片描述

    2.minix和GenericViewSet流程图

    在这里插入图片描述

    3.minix和GenericViewSet关系详情流程图

    在这里插入图片描述

    六、rest_framework导图

    在这里插入图片描述

  • 相关阅读:
    使用maven 3.8.3 创建并运行java web项目
    ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
    【NumPy基础(05)常用函数】
    js的sort()函数
    读程序员的制胜技笔记08_死磕优化(上)
    RabbitMQ队列持久化的重要性与意义
    Head First设计模式(阅读笔记)-09.模板方法模式
    Java实现 leetcode-946. 验证栈序列
    互动直播UI设置 之 主播UI
    C++中的结构体以及和类的区别
  • 原文地址:https://blog.csdn.net/weixin_44145338/article/details/132694418