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装饰器来继续让写在视图类的方法,可以被访问到
从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
原文地址:https://www.cnblogs.com/gfeng/p/14674997.html