zoukankan      html  css  js  c++  java
  • Django REST framework

    drf 响应格式和请求格式配置(了解)

    配置响应格式

    1 在配置文件中配置
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
            'rest_framework.renderers.JSONRenderer',  # json渲染器
             'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
        )
    }
    
    2 在浏览器访问就是浏览器方式,用postman访问就是json格式,ajax请求就是json格式
    
    
    3 原来没有配置,为什么显示浏览器方式和json的样子
    4 drf也有一套默认配置文件,默认就配了两个响应类
    
    5 局部配置某个视图类的响应格式,在视图类中配置
    renderer_classes = []

    配置能够解析的格式(urlencoded,formdata,json)

    什么是解析器?在DRF中,解析器是一个类列表,当每次接收到请求时,RDF会根据请求头中的Content-type,来指定使用哪钟解析方法去解析数据。当content-type与解析器列表均不匹配时,则会报解析失败。

    1 在setting中配置解析器列表
    REST_FRAMEWORK = {
        'DEFAULT_PARSER_CLASSES': [
            # 解析json格式数据({"user": "zhubao"}),解析成功后,request.data类型为dict
            'rest_framework.parsers.JSONParser',
            # 解析form表单格式数据(user=zhubao),解析成功后,request.data类型为QuerySet
            'rest_framework.parsers.FormParser',
            # (用的较少),解析较为复杂的form表单格式数据,解析成功后,request.data类型为QuerySet
            'rest_framework.parsers.MultiPartParser'
        ]
    }
    2 它就只能解析三种请求编码格式(urlencoded,formdata,json)
    
    3 局部使用,在视图类中配置
    from rest_framework.parsers import JSONParser, FormParser
        parser_classes = [FormParser]

    需要注意的是,一般get请求中,请求头没有Content-type字段,请求体内也没有值,request.data是空字典,因此解析器也不会生效,解析器更多的是针对POST、PUT请求。

    若settings.py与视图中均未设置解析器,DRF默认提供三种解析类,即:JSONParser, FormParser,MultiPartParser,每次请求根据Content-type来匹配使用哪种方式来解析。

    原理:

    • APIViewdispatch方法中,执行initialize_request 方法

    • 再执行get_parsers方法

    • 会循环实例化parser_classes中的解析器类,进行解析。

    封装自己的Response对象

    low版本

    # 封装
    
    class MyResponse():
        def __init__(self):
            self.status = 100
            self.msg = None
        @property
        def get_dict(self):
            return self.__dict__
    
    # 使用
    
    #### 原来的写法
    # class Test(APIView):
    #     def get(self,request):
    #         response={'status':'100','msg':None}
    #         #写一堆逻辑
    #         response['data']={'name':'lqz','age':19}
    #         response.data={}
    #
    #         return Response(response)
    
    ###自己封装了low   response后
    from app01.response import MyResponse
    class Test(APIView):
        def get(self, request):
            response = MyResponse()
            # 写一堆逻辑
            response.status=101
            response.msg='失败了'
            response.data={'name': 'lqz', 'age': 19}
    
            return Response(response.get_dict)

    高级版本

    # 在app目录下手动创建response.py文件,名字随意
    # 自定义一个APIResponse类,继承drf的Response
    from rest_framework.response import Response
    class APIResponse(Response):
        def __init__(self, code=100, msg=None, data=None, status=None,
                     template_name=None, headers=None,
                     exception=False, content_type=None, **kwargs):
            dic = {'status': code, 'msg': msg}
            if data: # 如果data有值,说明要往里面放东西
                dic['data'] = data 
            if kwargs: # 自定义传的参数会添加到字典里
                dic.update(kwargs)
    
            super().__init__(data=dic, status=status,
                             template_name=template_name, headers=headers,
                             exception=exception, content_type=content_type)
    
            
    ### 使用,在视图类中
    from app01.response import APIResponse # 先导入自定义的类
    return APIResponse(msg='成功了',data={'name': 'lqz', 'age': 19},next=9)

    drf自动生成路由

    1 三种路由写法
          - path('test/', views.Test.as_view()),
          -path('test/', views.Test.as_view({'get':'send_email'})),
         -自动生成路由
    # 1 导入路由类
    from rest_framework.routers import SimpleRouter, DefaultRouter
    # DefaultRouter生成的路由更多一点,多了一个根的路由(没有用)
    # 2 实例化得到对象
    router = SimpleRouter()
    # 3 注册路由
    
    router.register('books', views.BookView)
    # router.register('publish', views.PublishView)
    
    # print(router.urls) # 自动生成的路由
    
    from django.contrib import admin
    from django.urls import path,include
    from app01 import views
    
    urlpatterns = [
        # 4 用include把自动生成的路径加入到urlpatterns
        path('api/v1/', include(router.urls)),
        # path('api/v2', include(router.urls))
        # path('admin/', admin.site.urls),
        # path('test/', views.Test.as_view()),
        # path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
        # path('books/<int:pk>', views.BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
    ]
    # 4 把自动生成的路径加入到urlpatterns
    # urlpatterns+=router.urls
    
    # a=[1,2,3]
    # b=[4,5,6]
    # print(a+b)

    重点:ViewSetMixin+9个视图字类才能用自动生成路由

    对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。

    REST framework提供了两个router

    • SimpleRouter
    • DefaultRouter

    DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

    添加路由数据

    可以有两种方式:

    urlpatterns = [
        ...
    ]
    urlpatterns += router.urls

    urlpatterns = [
        ...
        url(r'^', include(router.urls))
    ]

    action装饰器

    在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用rest_framework.decorators.action装饰器。

    以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。

    1 作用:给自动生成路由的视图类再定制一些路由
       methods 请求方式,detail是否带pk
        methods第一个参数,传一个列表,列表中放请求方式
    2 用法一:detail布尔类型,detail=False
        
        # api/v1/books/sen_email/
        @action(methods=['GET'], detail=False)
        def sen_email(self, request, *args, **kwargs):
            print(args)
            print(kwargs)
            return APIResponse(msg='发送成功')
        
    3 方法二:detail布尔类型,detail=True
        # api/v1/books/1/sen_email/
        @action(methods=['GET'], detail=True)
        def sen_email(self, request, *args, **kwargs):
            # pk=1
            print(args)
            print(kwargs)
            return APIResponse(msg='发送成功')

    drf知识回顾

    1 drf入门
        -web开发模式:分离和混合
           -api接口:接口
        -postman的使用(http客户端)
        -restful-10条规范
        -drf是什么,能做什么(快速写符合resful规范的接口)
        -分析了执行流程:APIView
            -重写了dispatch
           -包装了新的request:drf的request
            -self.initial
                -请求格式处理,认证,权限,频率
            -处理了全局异常   
            -处理了响应
        -Request对象:data,取其他值和属性时跟原来一样
               
    2 序列化器
        -Serializer,ModelSerializer
        -写一个类继承Serializer
        -在类中写字段,
        -字段参数:read_only,write_only
        -视图类中使用:ser=Serilaizer(要序列化的对象,many=True)
        -ser.data
        -反序列化
        -ser=Serilaizer(data=字典)
        -ser.is_valid()
        -ser.save():Serializer需要重写update和create
        -反序列化的修改
        -ser=Serilaizer(instance=对象,data=字典)
        
        
        -ModelSerializer
        -class Meta:
            model=表模型
           fields='__all__'
            extra_kwargs={'name';{}}
        -重写字段
        name=serilaizer.CharField(source='xx')
        name=serilaizer.SerializerMethodField()
        def get_name(self,obj):
            return 'sb'+obj.name
        子序列化
        publish=PublishSerializer()
    2.1 序列化类的源码
        -many控制了谁
       -局部钩子和全局钩子
        -source为什么填publish.name  方法
        
    3 请求和响应
        -自己封装了一个响应对象(low,高级)
           -通过配置,配置请求和响应(全局配置,局部配置)
        
    4 视图
        -APIView,GenericAPIView
       -5个视图扩展类
        -9个视图子类
            -写一个删除接口(只需要继承DestroyAPIView,写上那两个类属性)
       -视图集
        -ViewSetMixin:路由就不一样了
    
    4.1 写一个删除接口,但是,删除后要记录日志
    
    5 自动生成路由
        -SimpleRouter
           -ViewSetMixin+9个子类视图才能自动生成路由
    6 action装饰器
        -自动生成路由后,使用action装饰器来继续让写在视图类的方法,可以被访问到
    从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
  • 相关阅读:
    Oracle存储过程格式
    Parallel并行运算实例
    唐让的领航少年
    株洲县阳光三农网
    株洲县招商网
    利用css新属性appearance优化select下拉框
    谈谈我的出差感想
    颜色表及html代码
    jquery中DOM的操作方法
    HTML DOM的nodeName,nodeValue,nodeType介绍
  • 原文地址:https://www.cnblogs.com/gfeng/p/14674997.html
Copyright © 2011-2022 走看看