04.Django REST framework - 响应格式和请求格式配置,解析器,自动生成路由、action装饰器
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 = []
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来匹配使用哪种方式来解析。
原理:
-
在
APIView的dispatch方法中,执行initialize_request方法 -
再执行
get_parsers方法 -
会循环实例化
parser_classes中的解析器类,进行解析。
# 封装
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)
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))
]
在视图集中,如果想要让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装饰器来继续让写在视图类的方法,可以被访问到


浙公网安备 33010602011771号