视图集额外动作;路由router;装饰action;认证;限流;分页;过滤;排序;异常处理;接口文档;vue全区组件,局部组件;分页对象响应返回指定

前天复习

  • write_only:只写;只进行反序列化,不进行序列化
  • read_only:只读;只进行序列化,不进行反序列化

1,视图集额外动作

  • 目的: 可以给视图集添加额外的动作(方法)

  • 操作流程:

    • 1, 子路由

      • from django.conf.urls import url
        from . import views
        
        urlpatterns = [
            url(r'^books/$',views.BookInfoModelViewSet.as_view({"get":"list","post":"create"})),
            url(r'^books/(?P<pk>\d+)/$',views.BookInfoModelViewSet.as_view({"get":"retrieve","put":"update","delete":"destory"})),
        
            url(r'^books/bread/$',views.BookInfoModelViewSet.as_view({"get":"bread_book"})),
        ]
        
    • 2, 类视图

      • from django.shortcuts import render
        from rest_framework.viewsets import ModelViewSet
        from booktest.models import BookInfo
        from booktest.serializers import BookInfoModelSerializer
        from rest_framework.response import Response
        
        #1,视图集
        class BookInfoModelViewSet(ModelViewSet):
            queryset = BookInfo.objects.all()
            serializer_class = BookInfoModelSerializer
        
            #1,获取阅读量大于20的书籍
            def bread_book(self,request):
                #1,获取指定书籍
                books = BookInfo.objects.filter(bread__gt=20)
        
                #2,创建序列化器对象
                serializer = self.get_serializer(instance=books,many=True)
        
                #3,返回响应
                return Response(serializer.data)
        
            #2,修改书籍编号为1的, 阅读量为99
        
        
    • 3, 序列化器

      • from rest_framework import serializers
        from booktest.models import BookInfo
        
        #1,模型类序列化器
        class BookInfoModelSerializer(serializers.ModelSerializer):
            class Meta:
                model = BookInfo
                fields = "__all__"
        

2,视图集额外动作,partial

  • 目的: 可以编写额外动作添加参数, 并且更新局部信息

  • 操作流程:

    • 1, 子路由

      •     url(r'^books/bread/(?P<pk>\d+)/$',
             views.BookInfoModelViewSet.as_view({"put":"update_book_bread"})),
        
        
    • 2, 类视图

      • class BookInfoModelViewSet(ModelViewSet):
            ...
        
            #2,修改书籍编号为1的, 阅读量为99
            def update_book_bread(self,request,pk):
                #1,获取参数
                book = self.get_object()
                data = request.data
        
                #2,创建序列化器,partial=True可以局部更新
                serializer = self.get_serializer(instance=book,data=data,partial=True)
        
                #3,校验,入库
                serializer.is_valid(raise_exception=True)
                serializer.save()
        
                #4,返回响应
                return Response(serializer.data,status=201)
        

3,路由router

  • 目的: 可以通过DefaultRouter和SimpleRouter两个类来自动生成路由

  • DefautRouter生成路由格式:

    • 特点: 共有三对路由

      • 1, 列表路由

      • 2, 详情路由

      • 3, 根路由 (什么参数也不用传)

    • from rest_framework.routers import SimpleRouter,DefaultRouter
      #1,创建路由对象
      router = DefaultRouter()
      
      #2,注册视图集
      router.register('books',views.BookInfoModelViewSet,basename="haha")
      urlpatterns += router.urls
      
      #3,输出结果
      print(urlpatterns)
      
      
      [
      
      <RegexURLPattern haha-list ^books/$>,  获取所有
      <RegexURLPattern haha-list ^books\.(?P<format>[a-z0-9]+)/?$>, 创建单个
      
      <RegexURLPattern haha-detail ^books/(?P<pk>[^/.]+)/$>, 
      <RegexURLPattern haha-detail ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>, 
      
      <RegexURLPattern api-root ^$>, 
      <RegexURLPattern api-root ^\.(?P<format>[a-z0-9]+)/?$>
      
      ]
      
      
    • SimpleRouter生成路由格式:

      • 特点: 生成两个路由

        • 1, 列表路由
        • 2, 详情路由
  • 操作流程:

    • 1, 子路由

      • from rest_framework.routers import SimpleRouter,DefaultRouter
        #1,创建路由对象
        router = SimpleRouter()
        
        #2,注册视图集
        router.register('books',views.BookInfoModelViewSet,basename="haha")
        urlpatterns += router.urls
        
        #3,输出结果
        print(urlpatterns)
        
        [
        <RegexURLPattern haha-list ^books/$>, 
        <RegexURLPattern haha-detail ^books/(?P<pk>[^/.]+)/$>
        ]
        
  • 注意点:

    • 1, 使用DRF可以自动根据前端需要的类型, 返回对应格式的数据
    • 2, 请求的时候在请求头中标记, Accept即可
    • 3, 只有视图集,才能自动生成路由

4,装饰action

  • 目的: 可以通过action装饰方法, 自动生成路由

  • 操作流程:

    • 1, 类视图

    • from rest_framework.decorators import action
      
      #1,视图集
      class BookInfoModelViewSet(ModelViewSet):
          ...
      
          # 使用路由router自动生成路由后 不会处理我们自己定义的类,需要设置action
          @action(methods=['GET'], detail=False)  # 生成路由规则: 前缀/方法名/  detail处理是否需要携带参数
          def bread_book(self,request):
              ...
      
          #2,修改书籍编号为1的, 阅读量为99
          @action(methods=["PUT"],detail=True) #生成路由规则: 前缀/{pk}/方法名/
          def update_book_bread(self,request,pk):
              ...
      
      

5,认证Authentication

  • 目的: 可以参考官方文档, 配置认证内容

  • 操作流程:

    • 1, 全局配置(setteings.py)

      • # DRF配置信息
        REST_FRAMEWORK = {
            #1,全局认证
            'DEFAULT_AUTHENTICATION_CLASSES': [
                'rest_framework.authentication.BasicAuthentication', #此身份验证方案使用HTTP基本身份验证,用于测试使用
                'rest_framework.authentication.SessionAuthentication', #自己服务器认证用户
            ]
        }
        
    • 2, 局部配置(views.py)

      • #1,视图集
        class BookInfoModelViewSet(ModelViewSet):
            ...
        
            #1,局部认证
            authentication_classes = [SessionAuthentication]
        
  • 注意点:

    • 如果配置了全局和局部, 默认使用局部

6,权限Permissions

  • 目的: 可以参考官方文档, 配置权限内容

  • 操作流程:

    • 1, 全局权限配置(settings.py)

      • REST_FRAMEWORK = {
            #1,全局认证
            ...
        
            #2,全局权限
            'DEFAULT_PERMISSION_CLASSES': [
                # 'rest_framework.permissions.IsAuthenticated', #普通用户
                # 'rest_framework.permissions.AllowAny', #所有用户
                'rest_framework.permissions.IsAdminUser', #管理员户
            ]
        }
        
    • 2, 局部权限配置(views.py)

      • #1,视图集
        class BookInfoModelViewSet(ModelViewSet):
            ...
        
            #1,局部认证
        		...
        
            #2,局部权限
            # permission_classes = [AllowAny]
        

7,限流Throttling

  • 目的: 可以通过配置, 限制不同用户的访问次数

  • 操作流程:

    • 1, 全局配置

      • # DRF配置信息
        REST_FRAMEWORK = {
            #1,全局认证
            'DEFAULT_AUTHENTICATION_CLASSES': [
                'rest_framework.authentication.BasicAuthentication', #此身份验证方案使用HTTP基本身份验证,用于测试使用
                'rest_framework.authentication.SessionAuthentication', #自己服务器认证用户
            ],
        
            #2,全局权限
            # 'DEFAULT_PERMISSION_CLASSES': [
            #     # 'rest_framework.permissions.IsAuthenticated', #普通用户
            #     # 'rest_framework.permissions.AllowAny', #所有用户
            #     'rest_framework.permissions.IsAdminUser', #管理员户
            # ],
        
            #3,全局限流
            'DEFAULT_THROTTLE_CLASSES': [
                'rest_framework.throttling.AnonRateThrottle', #匿名用户(未授权用户)
                'rest_framework.throttling.UserRateThrottle' # 认证用户
            ],
            'DEFAULT_THROTTLE_RATES': {
                'anon': '2/minute',#设置匿名用户(未授权用户) 每分钟只能访问2次
                'user': '3/minute'# 设置认证用户每分钟只能访问3次
            },
        }
        
    • 2, 局部配置

      • #1,视图集
        class BookInfoModelViewSet(ModelViewSet):
            queryset = BookInfo.objects.all()
            serializer_class = BookInfoModelSerializer
        
            #1,局部认证
            # authentication_classes = [SessionAuthentication]
        
            #2,局部权限
            # permission_classes = [AllowAny]
        
            #3,局部限流
            throttle_classes = [AnonRateThrottle]
        

8, 可选限流

  • 目的: 可以定义可选限流, 用在不同的类视图中

  • 操作流程:

    • 1, 全局定义

      • # DRF配置信息
        REST_FRAMEWORK = {
            ...
            #4,可选限流
            'DEFAULT_THROTTLE_CLASSES': [
                'rest_framework.throttling.ScopedRateThrottle',
            ],
            'DEFAULT_THROTTLE_RATES': {
                'downloads': '3/minute',
                'uploads': '5/minute'
            }
        }
        
    • 2, 局部使用

      • class TestView(APIView):
            throttle_scope = "uploads"
            def get(self,request):
                return Response("testing....")
        

9,分页Pagination

  • 目的: 可以参考文档, 设置分页返回

  • 操作流程:

    • 1, 全局配置

      • REST_FRAMEWORK = {
            ...
          
            #5,全局分页
            'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
            'PAGE_SIZE': 2 ##每页显示数据
        }
        
    • 2, 局部配置

      • class BookInfoModelViewSet(ModelViewSet):
            ...
            
            # 5,局部分页
            #pagination_class = LimitOffsetPagination # ?limit=100(一页显示100条) 或者 ?offset=2(从第2条数据开始显示)&limit=100
            pagination_class = PageNumberPagination # ?page=4(指定显示页数) 或者 ?page=4&page_size=20(指定页显示数据的数量)
        
        

10, 自定义分页类

  • 目的: 可以自定义类, 实现指定分页大小效果

  • 操作流程:

    • 1, 类视图

      • 
        #自定义分页对象
        class MyPageNumberPagination(PageNumberPagination):
            #1,默认的大小
            page_size = 3
        
            #2,前端可以指定页面大小
            page_size_query_param = 'page_size'
        
            #3,页面的最大大小
            max_page_size = 5
        
        
        #1,视图集
        class BookInfoModelViewSet(ModelViewSet):
           ...
        
            # 6,自定义分页对象
            pagination_class = MyPageNumberPagination  # ?page=4(指定显示页数) 或者 ?page=4&page_size=20(指定页显示数据的数量)
        
        

11,过滤Filtering

  • 目的: 可以根据文档配置,进行过滤数据获取

  • 操作流程:

    • 1, 安装扩展django-filters

      • pip install django-filter
    • 2, 注册子应用

      • INSTALLED_APPS = [
            ...
            'django_filters',
        ]
        
    • 3, 全局配置

      • REST_FRAMEWORK = {
        		...
            'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
        }
        
    • 4, 全局配置(views.py)

      • class BookInfoModelViewSet(ModelViewSet):
        	....
          #7,局部过滤
          filter_backends = [DjangoFilterBackend]
          filterset_fields = ['id', 'btitle',"is_delete"]
          
          http://127.0.0.1:8000/books/?id=1
          http://127.0.0.1:8000/books/?btitle=射雕英雄传
          http://127.0.0.1:8000/books/?is_delete=False
        

12,排序OrderingFilter

  • 目的: 可以参考文档, 使用指定的字段进行排序

  • 操作流程:

    • 1, 类视图

      • class BookInfoModelViewSet(ModelViewSet):
        	....
              #8,局部排序
            filter_backends = [filters.OrderingFilter] # 导包路径: from rest_framework import filters
            
            ordering_fields = ['id', 'btitle','bread'] #查询格式: ?ordering=-bread,id 传什么,就可以按照什么排序
            
            http://127.0.0.1:8000/books/?ordering=id 依据id正序排序
            http://127.0.0.1:8000/books/?ordering=-id 依据id逆序排序   
            
            #可以传两个参数 依据btitle排序,相同的btitle再根据id排序  
            http://127.0.0.1:8000/books/?offset=3&ordering=btitle,id
        
        

13,异常处理Exceptions

  • 目的: 可以参考文档, 处理程序中的异常信息

  • 操作流程:

    • 1, 定义自定义处理方法(booktest/my_exception.py)

      • from rest_framework.views import exception_handler
        from rest_framework.response import Response
        from django.db import DatabaseError
        
        def custom_exception_handler(exc, context):
        
            #1,调用系统方法,处理了APIException的异常,或者其子类异常
            response = exception_handler(exc, context)
        
            #2,判断response是否有值
            if response is not None:
                response.data['status_code'] = response.status_code
            else:
                if isinstance(exc, DatabaseError):
                    response = Response("数据库大出血")
                else:
                    response = Response("其他异常!")
        
            return response
        
    • 2, 全局配置(settings.py)

      • REST_FRAMEWORK = {
          	...
            'EXCEPTION_HANDLER': 'booktest.my_exception.custom_exception_handler'
        }
        
    • 3, 测试(views.py)

      • class TestView(APIView):
            # throttle_scope = "uploads"
            def get(self,request):
        
                # raise DatabaseError("DatabaseError!!!")
                raise Exception("报错了!!!")
                # raise APIException("APIException!!!")
                # raise ValidationError("ValidationError!!!")
        
                return Response("testing....")
        

14,接口文档(了解)

  • 目的: 可以参考文档, 配置后端数据的入口文档

  • 操作流程:

    • 1,安装扩展

      • pip install coreapi
    • 全局配置(settings.py)

      REST_FRAMEWORK = {
        	...
          'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
      }
      
    • 2, 根路由

      • url(r'^docs/', include_docs_urls(title='我的API文档'))
    • 3, 修改字段说明信息

      • 模型类

        • btitle = models.CharField(max_length=20, verbose_name='名称',help_text="书籍标题")
      • 序列化器

        • #1,模型类序列化器
          class BookInfoModelSerializer(serializers.ModelSerializer):
              class Meta:
                  ...
          
                  extra_kwargs = {
                      'bread':{
                          'help_text':"书籍阅读量" #针对接口文档中各个字段的描述信息
                      }
                  }
          

15,vue组件介绍

  • 目的: 知道vue中组件的作用, 和页面的组成
  • 组件:
    • 用来管理页面中的对应的模块
  • 页面:
    • 一个页面可以由各种各样的组件嵌套构成
  • 结构:
    • DRF学习day3随堂笔记_数据

16,vue全局组件

  • 目的: 知道如何定义全局组件,并进行使用

  • 操作流程:

    • 1,组件定义

      • <script>
          // 1,定义全局组件
          Vue.component(
            'global_component',
            {
              template:"<h1>迪丽热巴</h1>"
            }
          )
        
          // 2,创建vue对象
          var vm = new Vue({
            el:"#app"
          })
        </script>
        
    • 2, 组件使用

      •     <div id="app">
                <!-- 1,使用组件 -->
                <global_component></global_component>
                <global_component></global_component>
            </div>
        

17,vue局部组件

  • 目的: 知道如何定义局部组件,并进行使用

  • 操作流程:

    • 1,定义局部组件

      •     <script>
                //1,定义局部组件
                var part_component = {
                    template:"<h1>古力娜扎</h1>"
                }
        
                //2,创建vue对象, 注册局部组件
                var vm = new Vue({
                    el:"#app",
                    components:{
                        part1:part_component,
                        part2:{
                            template:"<h1>马尔扎哈</h1>"
                        }
                    }
                })
        
            </script>
        
    • 2,使用局部组件

      •     <div id="app">
                <!-- 1,使用局部组件 -->
                <part1></part1>
                <part2></part2>
            </div>
        

18,全局组件,嵌套局部组件

  • 目的: 知道如何在全局组件中嵌套局部组件,并进行使用

  • 操作流程:

    • 1, 组件的嵌套定义

      •     <script>
                // 1,定义局部组件
                var part1 = {
                    template:"<span> 大头儿子 </span>"
                }
                var part2 = {
                    template:"<span> 围裙妈妈 </span>"
                }
        
                // 2,全局组件
                Vue.component(
                    'global_component',
                    {
                        template:"<div> 小头巴巴, <part1></part1>, <part2></part2></div>",
                        components:{part1,part2}
                    }
                )
        
                // 3,创建vue对象
                var vm = new Vue({
                    el:"#app"
                })
            </script>
        
    • 2, 使用

      • <div id="app">
          	<!-- 1,使用组件 -->
        	  <global_component></global_component>
        </div>
        

19,组件中绑定数据data

  • 目的: 可以在全局组件中定义data,并获取数据

  • 操作流程:

    • 1,全局组件定义data

      •     <script>
                // 1,全局组件
                Vue.component(
                    'global_component',
                    {
                        template:"<h1>迪丽热巴, {{name}} ,{{age}} </h1>",
                        data:function(){
                            return {
                                name:"刷我滴卡",
                                age:13
                            }
                        }
                        
                    }
                )
        
                // 2,vm对象
                var vm = new Vue({
                    el:"#app",
                    data: {
        
                    }
                })
            </script>
        
    • 2,使用

      •     <div id="app">
                <global_component></global_component>
            </div>
        

20, 分页对象响应返回指定

  • 目的:知道如何去改写, 分页对象的返回数据

  • 操作流程:

    • 1, 类视图(views.py)

      • #自定义分页对象
        class MyPageNumberPagination(PageNumberPagination):
            ...
        
            def get_paginated_response(self, data):
                return Response(OrderedDict([
                    ('haha', 'zhangsan'),
                    ('count', self.page.paginator.count),
                    ('next', self.get_next_link()),
                    ('previous', self.get_previous_link()),
                    ('results', data)
                ]))