zoukankan      html  css  js  c++  java
  • DRF 视图(View) 和 集合(Set) 讲解

    DRF 视图

    from django.shortcuts import render
    
    # Create your views here.
    from rest_framework.response import Response # DRF 中的响应
    from students.serializers import StudentModelSerializer # 序列化器
    from students.models import Student  # 模型
    from rest_framework.views import APIView # 基础视图类
    from rest_framework.generics import GenericAPIView # 通用视图类
    from rest_framework import status # 响应状态码code
    
    '''APIView 视图类'''
    '''
        作用:
            1. 传入Rest_Framework中的Request对象 不是Django中的HttpRequest对象
            2. 传入Rest_Framework中的Response对象 不是Django中的HttpResponse对象
            3. APIException 异常会被捕获到,处理成适合响应的信息
            4. 在dispatch() 路由分发前,会对请求进行身份验证,权限检查,流量控制
        属性
            authentication_classes : 列表/元组,身份认证
            permissoin_classes : 列表/元组,权限检查类
            throttle_classes : 列表/元组, 流量控制类
    '''
    
    class StudentAPIView(APIView):
    
        def get(self, request):
            student_list = Student.objects.all()
            serializer = StudentModelSerializer(instance=student_list, many=True)
    
            return Response(serializer.data)
    
        def post(self, request):
            data = request.data
            serializer = StudentModelSerializer(data=data, )
            serializer.is_valid(raise_exception=True)  # 不强制校验错误!
            ret = serializer.save()
            if ret:
                st = status.HTTP_201_CREATED
            else:
                st = status.HTTP_400_BAD_REQUEST
    
            return Response(serializer.data, status=st)
    
    
    '''GenericAPIView 通用视图类 '''
    '''
        属性:
            queryset : 指定列表视图的查询数据集合
            serializer_class :  指定视图使用的序列化器
            pagination_class :  分页控制类
            filter_backends : 过滤 
            lookup_field  :  查询单一数据对象 时使用的条件字段,默认值是'pk'
            loop_url_kwarg : 查询单一数据时URL中的参数关键名称,默认与lookup_field一致
        
        方法: 
            get_queryset(self)  : 获取所有数据
            get_serializer_class(self)  : 调整序列化器类
            get_serializer(self,args,*kwargs) : 获取序列化器对象
            get_object(self) : 获取一条数据
    '''
    
    class StudentGenericAPIView(GenericAPIView):
        '''
            # 必须指定两个参数
                1. 序列化器
                2. 数据集
            # 备注:  对视图类并没有简写 , 需要结合视图扩展类
        '''
        serializer_class = StudentModelSerializer
        queryset = Student.objects.all()
    
        def get(self, request):
            serializer = self.serializer_class(instance=self.get_queryset(), many=True)
            return Response(serializer.data)
    
        def post(self, request):
            data = request.data
            serializer = self.serializer_class(data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(serializer.data)
    
    
    '''
    # 通用视图类 + 视图混合类 
    # 衍生出 四种:
    Createmodelmixin  添加一条数据
    Listmodelmixin   获取所有数据
    Retrievemodelmixin 获取一条数据
    Destorymodelmixin   删除一条数据
    Updatemodelmixin    更新一条数据
    '''
    from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin
    
    class StudentGeneralModelMixinAPIView(GenericAPIView, CreateModelMixin, ListModelMixin, DestroyModelMixin):
        serializer_class = StudentModelSerializer
        queryset = Student.objects.all()
    
        def get(self, request):
            '''
                # 获取所有数据
            :param request:
            :return:
            '''
            return self.list(request)
    
        def post(self, request):
            '''
                # 保存数据
            :param request:
            :return:
            '''
            return self.create(request)
    
        def delete(self, request, pk):
            '''
                # 删除一条数据
            :param request:
            :param pk:
            :return:
            '''
            return self.destroy(request, pk)
    
    '''
        ### 基于 通用视图类和 视图混合类衍生
        CreateAPIView    创建一套数据
        ListAPIView      获取所有数据
        RetrieveAPIView  获取一条数据
        DestoryAPIView   删除一条数据
        UpdateAPIView    更新一条数据
        RetrieveUpdateAPIView 更新一条数据 
        RetrieveUpdateDestoryAPIView  更新或删除一条数据
    '''
    

    路由

    """DrfDemo URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/3.0/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  path('', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.urls import include, path
        2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
    """
    from django.contrib import admin
    from django.urls import path, re_path
    from . import views
    urlpatterns = [
        path('stu_api_view/',views.StudentAPIView.as_view()),
        path('stu_generic_api_view/',views.StudentGenericAPIView.as_view()),
        re_path('^stu_generic_model_mixin_api_view/$',views.StudentGeneralModelMixinAPIView.as_view()),
        re_path('^stu_generic_model_mixin_api_view/(?P<pk>d+)/$',views.StudentGeneralModelMixinAPIView.as_view()),
    ]
    

    DRF集合

    from django.shortcuts import render
    
    # Create your views here.
    from rest_framework.response import Response
    
    from students.models import Student
    from students.serializers import StudentModelSerializer
    from rest_framework.viewsets import ViewSet
    
    ''' 
        # 基类视图集 : ViewSet
            特点: 
                1. 需要手动指定执行方法 ,如:获取一条数据/获取多条数据
                2. 不同的路由需要在as_view() 方法中指定:http请求方法 反射到 不同的函数 
    '''
    
    
    class StudentAPIViewSet(ViewSet):
        def get_one_data(self, request, pk):
            '''
                # 查询一条数据
            :param request:
            :param pk:
            :return:
            '''
            student_list = Student.objects.get(pk=pk)
            serializer = StudentModelSerializer(instance=student_list)
            return Response(serializer.data)
    
        def get_all_data(self, request):
            '''
                # 查询所有数据
            :param request:
            :return:
            '''
            student_list = Student.objects.all()
            serializer = StudentModelSerializer(instance=student_list, many=True)
    
            return Response(serializer.data)
    
    
    '''
        # 通用视图集合 GenericViewSet
            特点:
                1. 提供了 序列化器 和 模型  , 为了 模型视图集 做铺垫
                2. 需要 手动维护 处理的函数
                2. 需要手动在as_view路由分发函数, 指定 http请求方法 对应的处理视图函数
                
    '''
    
    from rest_framework.viewsets import GenericViewSet
    
    
    class StudentGenericViewSet(GenericViewSet):
        serializer_class = StudentModelSerializer
        queryset = Student.objects.all()
    
        def retrieve(self, request, pk):
            '''
                查询一条
            :param request:
            :param pk:
            :return:
            '''
            student = self.get_object()
            serializer = self.get_serializer(instance=student)
    
            return Response(serializer.data)
    
        def list(self, request):
            student_list = self.get_queryset()
            serializer = self.get_serializer(instance=student_list, many=True)
            return Response(serializer.data)
    
    
    from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin
    
    '''
        # 通用视图集 和 视图混合类使用
            特点: 
                1. 不需要手动维护 http请求方法对应的 视图处理函数
                2. 需要哪个混合类的功能,需要手动继承
                
    '''
    
    
    class StudentGenericViewSetMixin(GenericViewSet, ListModelMixin, RetrieveModelMixin):
        serializer_class = StudentModelSerializer
        queryset = Student.objects.all()
    
        def get_top_2(self, request):
            student_list = self.get_queryset()[:2]
            serializer = self.get_serializer(instance=student_list, many=True)
            return Response(serializer.data)
    
    
    ''' 只读视图集 :ReadOnlyModelViewSet
        特点:
            1. 只提供了 list 和retrieve 2个函数
    '''
    from rest_framework.viewsets import ReadOnlyModelViewSet
    
    
    class StudentReadOnlyModelViewSetMixin(ReadOnlyModelViewSet):
        queryset = Student.objects.all()
        serializer_class = StudentModelSerializer
    
    
    '''
        # 模型视图集 StudentModelViewSetMixin
            特点: 
                1. 提供了5个处理函数
    '''
    from rest_framework.viewsets import ModelViewSet
    
    
    class StudentModelViewSetMixin(ModelViewSet):
        queryset = Student.objects.all()
        serializer_class = StudentModelSerializer
    
    
    ### Action  : 解决  一个路由和多个处理函数的映射
    '''
        # 在 视图集中,因为自定义视图方法的名字会各种各样,需要视图获得客户端请求的视图方法名
          request.action属性来查看      
    '''
    
    from rest_framework.decorators import action  # 装饰
    
    
    class StudentAPIViewSetAction(ViewSet):
    
        # 为什么: 用到action,是因为视图集中 存在自定义的方法名, 如果自定义函数较多,则路由会越写越多
            #   使用action 通过路由注册的方式,按照drf默认的规则生成 新的路由地址
        # action装饰器 使用:
            # 1. methods 指定 访问的HTTP请求方法,与flask类似
            # 2. detail 表示设置router路由类在生成路由的时候是否要加上 ,主键pk到URL地址栏中
        @action(methods=['get'], detail=True)
        def get_one_data(self, request, pk):
            '''
                # 查询一条数据
            :param request:
            :param pk:
            :return:
            '''
            # print(self.action)  # 获取Action:get_one_data  ,客户端调用通过HTTP调用到的处理视图函数
            student_list = Student.objects.get(pk=pk)
            serializer = StudentModelSerializer(instance=student_list)
            return Response(serializer.data)
    
        @action(methods=['get'], detail=False)
        def get_all_data(self, request):
            '''
                # 查询所有数据
            :param request:
            :return:
            '''
            student_list = Student.objects.all()
            serializer = StudentModelSerializer(instance=student_list, many=True)
    
            return Response(serializer.data)
    
    

    路由

    """DrfDemo URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/3.0/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  path('', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.urls import include, path
        2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
    """
    from django.contrib import admin
    from django.urls import path, re_path
    from . import views
    
    urlpatterns = [
    
        # 视图集 中的方法和地址,以及HTTP请求的绑定都是通过as_view()完成的
    
        # 基础视图集合  ViewSet
        path('stu_view_set/', views.StudentAPIViewSet.as_view({'get': 'get_all_data'})),
        re_path('stu_view_set/(?P<pk>d+)/', views.StudentAPIViewSet.as_view({'get': 'get_one_data'})),
    
        # 通用视图集合  GenericViewSet
        path('stu_generlic_view_set/', views.StudentGenericViewSet.as_view({'get': 'list'})),
        re_path('stu_generlic_view_set/(?P<pk>d+)/', views.StudentGenericViewSet.as_view({'get': 'retrieve'})),
    
        # 通用视图集  GenericViewSet 和 视图混合类 ListModelMixin, RetrieveModelMixin
        path('stu_generlic_view_set_mixin/', views.StudentGenericViewSetMixin.as_view({'get': 'list'})),
        path('stu_generlic_view_set_mixin/top/', views.StudentGenericViewSetMixin.as_view({'get': 'get_top_2'})),
        re_path('stu_generlic_view_set_mixin/(?P<pk>d+)/', views.StudentGenericViewSetMixin.as_view({'get': 'retrieve'})),
    
        # 只读 视图集 ReadOnlyModelViewSet  (包含 ListModelMixin, RetrieveModelMixin 混合类)
        path('stu_readonly_view_set_mixin/', views.StudentReadOnlyModelViewSetMixin.as_view({'get': 'list'})),
        re_path('stu_readonly_view_set_mixin/(?P<pk>d+)/',
                views.StudentReadOnlyModelViewSetMixin.as_view({'get': 'retrieve'})),
    
        # 模型 视图集  StudentModelViewSetMixin (包含所有混合类)
        path('stu_model_view_set_mixin/', views.StudentModelViewSetMixin.as_view({'get': 'list', 'post': 'create'})),
        re_path('stu_model_view_set_mixin/(?P<pk>d+)/',
                views.StudentModelViewSetMixin.as_view({'get': 'retrieve', 'delete': 'destroy', 'put': 'update'})),
    
        # ViewSet  ====>Action的查看
        path('stu_view_set_action/', views.StudentAPIViewSet.as_view({'get': 'get_all_data'})),
        re_path('stu_view_set_action/(?P<pk>d+)/', views.StudentAPIViewSet.as_view({'get': 'get_one_data'})),
    
    ]
    
    
    #### 基于action 装饰器 和 路由类 来生成路由,达到简写的目的
    # SimpleRouter    作用: 为视图 生成url路由, 不会生成根目录, <上线使用>
    # DefaultRouter   作用: 为视图 生成url路由
    
    from rest_framework.routers import SimpleRouter, DefaultRouter
    
    router = DefaultRouter()
    ### 注册视图集 ->生成视图集对应的路由方法
        # 1. 格式: router.register('路由前缀','视图集类','可选参数:路由别名前缀')
        # 2. 访问:
            # 访问单一数据 : http://127.0.0.1:8000/viewset/stu_view_set_action_auto/1/get_one_data/
            # 访问多条数据 : http://127.0.0.1:8000/viewset/stu_view_set_action_auto/get_all_data/
    router.register('stu_view_set_action_auto', views.StudentAPIViewSetAction,'action')
    
    # print(router.urls)
    urlpatterns += router.urls
    
  • 相关阅读:
    面试题:能谈谈Date、Datetime、Time、Timestamp、year的区别吗?
    面试题:对NotNull字段插入Null值 有啥现象?
    聊聊什么是慢查、如何监控?如何排查?
    谈谈MySQL的基数统计
    .vimrc
    HISKrrr的板子库
    CSP 模拟35
    晚测1
    CSP 模拟34
    nim板子题异或正确性YY
  • 原文地址:https://www.cnblogs.com/dengz/p/14286727.html
Copyright © 2011-2022 走看看