• DRF框架(django rest framework)


    1,DRF框架?

      Django REST framework 框架是一个用于构建Web API 的强大而又灵活的工具。通常简称为DRF框架 或 REST framework。

      Django REST framework 可以帮助我们大大提高REST API  的开发速度,目的就是简化代码

    2,序列化和反序列化

      序列化:将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等),例   如 Django中的模型类对象转换为字典或JSON字符串,这个转换过程我们称为序列化。

      反序列化:将其他格式(字典、JSON、XML等)转换为程序中的数据,例如将JSON字符串或字典转换保存为Django中的模型类对象,这个过程我们称为反序列化

      序列化(侠义):将对象转为字典,json 

      反序列化(侠义):将字典,json转换为对象

    3,Django REST framework 的使用:

      1,下载安装:pip install djangorestframework  

      2,settings中进行注册  INSTALL_APPS     ‘rest_framework’

      3,   DRF 框架序列化:只能将对象转换为字典,不能转换为json

      4,DRF框架反序列化:数据校验,数据保存(新增和更新)  

    4,使用序列化器必须先定义序列化器:

      序列化器的定义:

        class <序列化器类名> (serializer.Serailizers):

            字段 = serializers.字段类型(参数)

    5,序列化功能:

      1,创建序列化器类对象  serializer = 类名(user) (把对象放入类中)

      2,获取序列化后的数据  res = serializers.data()    print(res)

    6,反序列化功能:

      1,创建序列化器对象   serializer = 类名(data={xx}) 把前端传入的字典放入其中

      2,进行参数校验 serializer.is_valid   返回true 或 false  代表校验成功和失败

      3,获取校验失败的错误信息:serializers.errors   如果成功返回的是空字典

      4,获取校验后的数据:serializers.validated_data   返回的是校验成功后的有序字典orderdict

    7,序列化器使用的总结:

      1,无论是序列化还是反序列化都需要创建序列化器对象

        serializers = UserSerializer(instance = none,data={})

        序列化时,将序列化对象传给intsance

        反序列化时,将字典传给data

    8,序列化器类的通用参数:

      reade_only (该字段只在序列化时使用设为true)

      write_only     (该字段只在反序列化时使用设为true)

      read_only  和 write_only 不指定时为false ,表示序列化和反序列化时都使用

      required 只争对反序列化时使用,默认为true,代表反序列化时必须传入该字段参数,

      default 设置序列化或反序列化时的默认值  

      max_lengthmin_length:设置反序列化时的最大长度和最小长度

      max_valuemin_value:设置反序列化时的最大值和最小值

     9,序列化操作

      1,序列化单个对象 

    book = BookInfo.objects.get(id=1)  
    serizlizer = BookInfoSerializer(book) 
    res = serializer.data

      2,序列化多个对象

    books = BookInfo.objects.all()   #Queryset
    serializer = BookInfoSerializer(books,many=True)
    res = serializer.data

      3,关联对象 嵌套序列化

    #1,将关联对象序列化为关联对象的主键
    hbook = serializer.PrimarykeyRelatedFiled(label = '图书',read_only = true)
    
    或
    hbook = serializer.PrimarykeyRelatedFiled(label = '图书',queryset=BookInfo.objects.all())
    
    #2,使用指定的序列化器将关联对象一并序列化
    hbook = BookInfoSerializer()
    
    #3,将关联对象序列化为关联对象模型类__str__的返回值
    hbook = serializer.StringRelatedFiled(lable='图书')

    注意:和一个对象关联的对象如果有多个,在进行嵌套序列化字段定义时,需要加 many=true

    10 ,反序列化操作  (可以进行校验和保存)校验只能进行数据是否完整,类型是否正确,以及一些选项参数对data中的数据进行校验 

      1,  补充校验的三种方式:

      

     注意:方式一 :在定义序列化器类外定义一个函数进行校验,在字段后面添加 validators =  函数名 (不常用)

         方法二:在定义序列化器类里添加函数,其中函数名必须是 validate_<字段名>   (缺点是只能对单个字段进行校验)

        方法三 :  在定义序列化器类里添加函数,可以进行多个字段的对比,函数名必须是 validata  

       

      2,保存数据:

        前提:必须校验通过ser.is_valid()

        使用:serializer.save()    内部可能会调用序列化器类的create或update方法,(如果序列化器类继承serializer.Serializer,需要重写这两个方法,该父类为实现,如果继承serializer.ModelSerializer,父类已经实现)

        创建序列化器对象时,如果只传入instance,save()方法被调用,否则create()方法被调用(create方法调用时instance和data参数都要传入)

       3,ModelSerializer类的使用

        使用:序列化器需要对应是Django的模型类

        特点:自动生成序列化器类中的字段

            默认已经实现create和update方法

    11,APIView视图类

      APIView是View的子类,

      区别:1,请求对象:Request   

    request.data  :包含解析之后的请求体中的数据,相当于之前的request.POST  | request.body  | request.FILEs
    request.query_params : 包含了解析之后的查询字符串中的数据 QueryDict

          2,响应对象:response(原始的响应数据)

            根据客服端请求头中Accept自动转换为对应的格式,不需要指定,直接返回res.data ,默认返回json

          3, 自动处理APIException的子类异常和Http404

          4,其他权限,认证,权限,限流  (后面细说)

    12,GenericAPIView视图类 

    class  BookListView(GenericAPIView):
        #指定视图所使用的序列化器类
        serializer_class = BookInfoSerializer    #名字必须是serializer_class,父类已经定义,但为None,需要自己指定
      
        #指定视图所使用的查询集
        queryset = BookInfo.objects.all()     #名字也是必须是queryset,和上面一样,可以到源码进行查看

      继承genericAPIView后可以调用下面的方法:

      get_serializer_class :  获取指定的序列化器类

      get_serializer :获取指定的序列化器类对象

      get_queryset:获取指定的查寻集

      get_object : 从指定查询集查询一个对象进行返回,默认根据url地址提取的pk进行查询,所以不需要传递参数pk,该函数会制动从url中进行匹配

      注意:使用get_serializer_class 和get_serializer 之前必须先指定serializer_class

         使用get_queryset和get_object必须先指定queryset 属性

     

       2,GenericAPIView 和APIView 的区别:继承自APIView 

        1)  增加操作序列化器相关属性和方法

        2) 增加数据库查询相关属性和方法

        3) 过滤,排序,分页  (后面细说)

      3,GenericAPIView 案例:(增,删,改,查)

    #/books/
    class BookListView(GenericApIview):
        #指定视图使用的序列化器类
        serializer_class = BookInfoSerializer()   #序列化器类
        
        #指定查询集
        queryset = BookInfo.objects.all()
    
        #查询所有书籍
        def get(self,request):
            books = self.get_queryset()  # Queryset:查询集
            #将所有图书数据通过json进行返回
            ser = self.get_serializer(books,many=true)  #多个加many=true
            
            return Response(ser.data)    #ser.data 将序列化后的数据进行返回
        
    
        #新增书籍
        def post(self,request):
            #校验前端传入的数据
            ser = self.get_serializer(data=request.data)
            ser.is_valid(raise_exception=true)
            
            #保存数据
            ser.save()   #调用序列化器类中的create方法
        
            #将新增的图书进行返回
            return Response(ser.data,status=status.HTTP_201_CREATE)
    class BookDetailView(GenericAPIView):
        serializer_class = BookInfoSerializer()
        queryset = BookInfo.objects.all()
        
        #查找指定图书
        def get(self,request,pk):
            book = self.get_object()   #不用传参数,改函数会自动在url中查找pk的值
            
            ser = self.get_serializer(book)
              
            return Response(ser.data)
    
    
        #修改指定图书
        def put(self,request,pk):
            book = self.get_object()
    
             #参数校验
            ser = self.get_serializer(book,data=request.data)
            ser.is_valid(raise_exception=true) 
            #校验通过保存数据
            ser.save()        
            return Response(res.data) 
    
        #删除指定图书
        def delete(self,request,pk):
           book = self.get_object()
           book.delete()
           return Response(status=status.HTTP_204_NO_CONTENT)       

    13 , Mixin扩展类

      继承object,不能单独使用,需要配合GenericAPIView来进行使用

      DRF框架提供5个Mixin扩展类,就是对上面五个函数进行封装:

      

    # 自己封装Mixin扩展类
    class MyListModelMixin(object):
        def list(self, request, *args, **kwargs):
            """封装获取一组数据的通用代码流程"""
            query_set = self.get_queryset()  # QuerySet:查询集
            serializer = self.get_serializer(query_set, many=True)
            return Response(serializer.data)
    
    
    class MyCreateModelMixin(object):
        def create(self, request, *args, **kwargs):
            """封装新增一条数据通用代码流程"""
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save()  # 调用序列化器类中的create
            return Response(serializer.data, status=status.HTTP_201_CREATED)
    
    
    # /books/
    class BookListView(mixins.ListModelMixin,
                       mixins.CreateModelMixin,
                       GenericAPIView):
        # 指定视图使用的序列化器类
        serializer_class = BookInfoSerializer
        # 指定视图使用的查询集
        queryset = BookInfo.objects.all()
    
        # serializer_class = HeroInfoSerializer
        # queryset = HeroInfo.objects.all()
    
        def get(self, request):
            return self.list(request)
    
        def post(self, request):
           return self.create(request)
    
    
    class MyRetrieveModelMixin(object):
        def retrieve(self, request, *args, **kwargs):
            """封装获取指定数据通用代码流程"""
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response(serializer.data)
    
    # obj = MyRetrieveModelMixin()
    # obj.retrieve()
    
    
    class MyUpdateModelMixin(object):
        def update(self, request, *args, **kwargs):
            """封装修改指定数据通用代码流程"""
            instance = self.get_object()
            serializer = self.get_serializer(instance, data=request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save()  # 调用序列化器类中的update
            return Response(serializer.data)
    
    
    class MyDestroyModelMixin(object):
        def destroy(self, request, *args, **kwargs):
            """封装删除指定数据的通用代码流程"""
            instance = self.get_object()
            instance.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
    
    
    # 系统封装的
    # /books/(?P<pk>d+)/ # /books/100/ class BookDetailView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, GenericAPIView): serializer_class = BookInfoSerializer queryset = BookInfo.objects.all() def get(self, request, pk): return self.retrieve(request, pk) def put(self, request, pk): return self.update(request, pk) def delete(self, request, pk): return self.destroy(request, pk)

    14,子类视图:

      继承了GenericAPIView和对应的Mixin扩展类,而且还提供了对应的请求处理函数(get,post)

    class BookListView(ListAPIView):
        serializer_class = BookInfoSerializer
        queryset = BookInfo.objects.all()

    15,视图集:

      概念:将一组相关的API接口放在同一个类中,这个类就叫视图集。

      基本使用: 

    1,继承父类ViewSet
    2, 视图集中处理方法不以请求方发命名(get,..),而是以对应的操作命名:list,create,retrieve,update,destroy
    3, 进行url地址配置时,需要指明请求方式,请求url地址时对应的处理方法

      视图集父类:

      ViewSet(继承ViewSetMixin和APIView)

      GenericViewSet(继承ViewSetMixin和GenericAPIView)   可以配合Mixin扩展类来提供对应的处理函数

      ModelViewSet(继承GenericviewSet和5个Mixin扩展类)  常用

      ReadOnlymodelViewSet(继承GenericViewSet和2个Mixin扩展类) (ListModelMixin和RetievemodelMixin)

    视图集添加额外的API方法即可,注意不要和其他API方法名有冲突 

    * 直接在视图集中添加API方法即可,注意不要和其他API方法名有冲突
    * 添加之后需要进行url地址配置

    16,路由router

      作用:动态生成视图集中API接口的url 配置项

      使用:

    lookup_value_regex:

      设置router生成路由时,从url中提取pk参数对应的正则表达式

    视图集中额外API接口配置项生成:

    需要添加action装饰器(导入 from rest_framework.decorators import action)

    注意:detail = true或false,看是否需要从url中提取PK,需要就设置为true

    defaultRouter和SimpleRouter区别:

    1,DefaultRouter多生成一个根路径/配置项

    2,每个配置项都可以直接根据.json,返回json数据

    17 ,认证 | 权限 | 限流

      1,认证:

      DRF框架默认全局支持两种认证方法:session认证和基本认证

      可以修改全局的认证方式:

      

    REST_FRAMEWORK = {
        # 修改全局认证方式
        'DEFAULT_AUTHENTICATION_CLASSES': (
             'rest_framework.authentication.SessionAuthentication', # 仅支持session认证
        ),
    }

    # 指定视图自己的认证方式,此处仅支持session认证
    authentication_classes = [SessionAuthentication]

      权限:

      1,DRF框架默认全局权限设置为:AllowAny,代表允许所有人访问

      2,可以修改全局的权限控制方式

    REST_FRAMEWORK = {
            # 修改全局权限控制方式
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated', # 允许认证用户
        )
    }

     指定视图自己的权限控制方式,此处代表只有认证过的用户才能访问本视图集中的接口
     permission_classes = [IsAuthenticated]

       3,自定义权限控制类

    class MyPermission(BasePermission):
        def has_permission(self, request, view):
            """判断用户对使用这个权限控制类的视图中的API接口是否有访问权限"""
            return True
    
        def has_object_permission(self, request, view, obj):
            """判断用户对使用这个权限控制类中视图中某个对象是否有访问权限"""
            # get_object:
            # 需求:id为1或3的对象用户可以访问,其他的对象不允许访问
            if obj.id in (1, 3):
                return True
            return False
    View Code

     

    限流:限制用户访问接口的频率

      1,分别限流

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES': (
            # 针对未登录(匿名)用户的限流控制类
            'rest_framework.throttling.AnonRateThrottle',
            # 针对登录(认证)用户的限流控制类
            'rest_framework.throttling.UserRateThrottle'
        ),
        # 指定限流频次
        'DEFAULT_THROTTLE_RATES': {
            # 认证用户的限流频次
            'user': '5/minute',
            # 匿名用户的限流频次
            'anon': '3/minute',
        },
    }
    View Code

    统一限流:

    REST_FRAMEWORK = {
        # 针对匿名用户和认证用户进行统一的限流控制
        'DEFAULT_THROTTLE_CLASSES': (
            'rest_framework.throttling.ScopedRateThrottle',
        ),
    
        # 指定限流频次选择项
        'DEFAULT_THROTTLE_RATES': {
            'upload': '3/minute',
            'contacts': '5/minute'
        },
    }

      统一限流,还需要在视图中通过属性throttle_scope指定限流选项

    18 ,过滤 | 排序 | 分页

    过滤:

      1,安装:pip install django-filter

      2,注册子应用,添加过滤配置

      3,在视图中通过filter_fields属性指定过滤字段

    排序:

      在视图中排序设置:(前端在查询字符串中指定排序字段,http://xxxx.com/?ordering=id)

      

    分页:

      设置全局分页类

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 5  # 页容量
    }
    View Code

    注意:设置全局分页类之后,默认情况下凡是使用ListModelMixin中的List返回数据的API,都会使用全局分页类进行分页,如果要取消,可以在该视图中设置:

      pagination_class = None

    自定义分页类;

    # ?page=<页码>&pagesize=<页容量>
    class StandardResultPagination(PageNumberPagination):
        # 默认分页页容量
        page_size = 3
        # 指定页容量参数的名称
        page_size_query_param = 'pagesize'
        # 分页最大页容量
        max_page_size = 5

    注意:自定义分页类可以设置为全局分页类或指定视图自己使用的分页类

    19,异常处理

      只要继承了APIView或者它的子类,视图中的处理异常:APIException子类异常或HTTP404,DRF框架都可以自动处理

    自定义异常处理函数:

    from rest_framework.views import exception_handler as drf_exception_handler
    from rest_framework.response import Response
    from rest_framework import status
    from django.db import DatabaseError
    
    
    def exception_handler(exc, context):
        # 调用DRF框架默认异常处理函数
        response = drf_exception_handler(exc, context)
    
        if response is None:
            # DRF框架不能处理此异常,自己处理:DatabaseError
            if isinstance(exc, DatabaseError):
                response = Response({'detail': '数据库错误!!!'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
    
        return response
    复制代码

    修改EXCEPTION_HANDLER配置项

    REST_FRAMEWORK = {
            'EXCEPTION_HANDLER': 'booktest.utils.exceptions.exception_handler'
    }
  • 相关阅读:
    区间筛——模板
    I NEED A OFFER!
    dp入门(A)
    java如何创建类
    二维数组
    一维数组
    循环练习记录
    根据浏览器屏幕分辨率不同使用不同的css样式——响应式
    jquery 淡入淡出动画效果例子
    toggle()在新闻热点上的运用
  • 原文地址:https://www.cnblogs.com/wjun0/p/11723635.html
Copyright © 2020-2023  润新知