DRF框架和序列化器限流分页相关
web开发两种模式
开发模式 | 说明 |
---|---|
前后端不分离 | 前端展示的数据效果最终是由后端进行控制的,由后端使用模板进行模板的渲染,将渲染之后的内容返回给客户端进行显示 |
前后端分离 | 后端服务器只返回前端所需要数据,前端获取数据之后自己控制数据怎么进行展示 |
3. RestAPI接口设计风格
GET /books/: 获取所有图书,返回所有图书信息
POST /books/: 新建一本图书,返回新建的图书信息
GET /books/id/: 获取指定图书,返回指定图书信息
PUT /books/id/: 修改指定图书,返回修改图书信息
DELETE /books/id/: 删除指定图书,返回空文档
关键点:
- url地址尽量使用名词,不要出现动词。
- 采用不同请求方式,执行不同操作。
- 过滤参数放在查询字符串中。
- 响应状态码选择。
- 响应数据返回json。
4. 使用Django知识自定义RestAPI接口
准备工作->创建应用->定义模板类->生成数据表->添加测试数据。
使用Django知识自定义RestAPI接口:
1. 获取所有图书的信息 GET /books/
2. 新增一本图书信息 POST /books/
3. 获取指定的图书信息 GET /books/(?P<pk>\d+)/
4. 修改指定的图书信息 PUT /books/(?P<pk>\d+)/
5. 删除指定的图书信息 DELETE /books/(?P<pk>\d+)/
5. RestAPI接口开发时的工作
概念 | 说明 |
---|---|
序列化 | 将程序中一种数据结构类型转化为其他的数据格式,这个过程叫做序列化。在我们前面例子中,将模型对象转化为python字典或json数据,这个过程可以认为是序列化过程。 |
反序列化 | 将其他格式数据转换为程序中数据,这个过程叫做反序列化。在我们前面例子中,将客户端发送的数据保存在模型对象中,这个过程可以认为是反序列化过程。 |
主要工作
1)将请求数据保存在模型对象中(反序列化)。
2)操作数据库。
3)将模型对象转换为前端所需的格式(序列化)。
DRF框架
类名 | 说明 |
---|---|
APIView | 1)继承自View,封装了Django 本身的HttpRequest对象为Request对象。2)统一的异常处理。 3)认证&权限&限流。 |
GenericAPIView | 1)继承自APIView,提供了操作序列化器和数据库数据的方法,通常和Mixin扩展类配合使用。2)过滤&分页。 |
1. Mixin扩展类
DRF提供了5个扩展类,封装了5个通用的操作流程。
类名 | 说明 |
---|---|
ListModelMixin | 提供了一个list方法,封装了返回模型数据列表信息的通用流程。 |
CreateModelMixin | 提供了一个create方法,封装了创建一个模型对象数据信息的通用流程。 |
RetrieveModelMixin | 提供了一个retrieve方法,封装了获取一个模型对象数据信息的通用流程。 |
UpdateModelMixin | 提供了一个update方法,封装了更新一个模型对象数据信息的通用流程。 |
DestroyModelMixin | 提供了一个destroy方法,封装了删除一个模型对象数据信息的通用流程。 |
2. 子类视图
为了方便我们开发RestAPI,DRF框架除了提供APIView和GenericAPIView视图类之外,还提供了一些子类视图类,这些子类视图类同时继承了GenericAPIView
和对应的Mixin扩展类,并且提供了对应的请求方法。
类名 | 说明 |
---|---|
ListAPIView | 1)继承自ListModelMixin和GenericAPIView。2)如果想定义一个视图只提供列出模型列表 信息的接口,继承此视图类是最快的方式。 |
CreateAPIView | 1)继承自CreateModelMixin和GenericAPIView。2)如果想定义一个视图只提供创建一个模型信息 的接口,继承此视图类是最快的方式。 |
RetrieveAPIView | 1)继承自RetrieveModelMixin和GenericAPIView。2)如果想定义一个视图只提供获取一个模型信息 的接口,继承此视图类是最快的方式。 |
UpdateAPIView | 1)继承自UpdateModelMixin和GenericAPIView。2)如果只想定义一个视图只提供更新一个模型信息 的接口,继承此视图类是最快的方式。 |
DestroyAPIView | 1)继承自DestroyModelMixin和GenericAPIView。2)如果只想定义一个视图只提供删除一个模型信息 的接口,继承此视图类是最快的方式。 |
ListCreateAPIView | 1)继承自ListModelMixin,CreateModelMixin和GenericAPIView。2)如果只想定义一个视图提供列出模型列表 和创建一个模型信息 的接口,继承此视图类是最快的方式。 |
RetrieveUpdateAPIView | 1)继承自RetrieveModelMixin,UpdateModelMixin和GenericAPIView。2)如果只想定义一个视图提供获取一个模型信息 和更新一个模型信息 的接口,继承此视图类是最快的方式。 |
RetrieveDestroyAPIView | 1)继承自RetrieveModelMixin,DestroyModelMixin和GenericAPIView。2)如果只想定义一个视图提供获取一个模型信息 和删除一个模型信息 的接口,继承此视图类是最快的方式。 |
RetrieveUpdateDestoryAPIView | 1)继承自RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin和GenericAPIView。2)如果只想定义一个视图提供获取一个模型信息 和更新一个模型信息 和删除一个模型信息 的接口,继承此视图类是最快的方式。 |
示例1:
# 需求1:写一个视图,只提供一个接口
1. 获取一组图书数据 GET /books/
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
# 需求2:写一个视图,只提供一个接口
1. 获取指定的图书数据 GET /books/(?P<pk>\d+)/
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
# 需求3:写一个视图,只提供两个接口
1. 获取指定的图书数据 GET /books/(?P<pk>\d+)/
2. 更新指定的图书数据 PUT /books/(?P<pk>\d+)/
class BookDetailView(RetrieveUpdateAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
3. 视图集类
将操作同一资源的处理方法放在同一个类中(视图集),处理方法不要以请求方式命名,而是以对应的action命名。
list: 提供一组数据
create: 创建一条新数据
retrieve: 获取指定的数据
update: 更新指定的数据
destroy: 删除指定的数据
进行url配置时需要指明请求方法和处理函数之间的对应关系。
类名 | 说明 |
---|---|
ViewSet | 1)继承自ViewSetMixin和APIView。2)如果使用视图集时不涉及数据库和序列化器的操作,可以直接继承此类。 |
GenericViewSet | 1)继承自ViewSetMixin和GenericAPIView。2)如果使用视图集涉及数据库和序列化器的操作,可以直接继承此类。 |
ModelViewSet | 1)继承自5个Mixin扩展类和GenericViewSet。2)如果使用视图集想一次提供通用的5种操作,继承这个类是最快的。 |
ReadOnlyModelViewSet | 1)继承自ListModelMixin,RetrieveModelMixin和GenericViewSet。2)如果使用视图集想一次提供list操作和retrieve操作,继承这个类是最快的。 |
示例1:
# 需求1:写一个视图集,提供以下两种操作
1. 获取一组图书信息(list) GET /books/
2. 新建一本图书信息(create) POST /books/
class BookInfoViewSet(ListModelMixin,
CreateModelMixin,
GenericViewSet)
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
# 需求2:写一个视图集,提供以下两种操作
1. 获取一组图书信息(list) GET /books/
2. 获取指定图书信息(retrieve) GET /books/(?P<pk>\d+)/
class BookInfoViewSet(ReadOnlyModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
# 需求3:写一个视图集,提供以下三种操作
1. 获取一组图书信息(list) GET /books/
2. 获取指定图书信息(retrieve) GET /books/(?P<pk>\d+)/
3. 更新指定图书信息(update) PUT /books/(?P<pk>\d+)/
class BookInfoViewSet(UpdateModelMixin,
ReadOnlyModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
注: 除了常见的5种基本操作之外,如果想给一个视图集中添加其他处理方法,直接在视图集中定义即可。
4. 路由Router
1)路由Router是专门配合视图集来使用的,可以使用Router自动生成视图集中相应处理函数对应的URL配置项。
2)使用Router自动生成视图集中相应处理函数对应的URL配置项时,除了常见的5种基本操作之外,如果视图集中有添加的其他处理方法,则需要给这些方法加上action装饰器之后,才会动态生成其对应的URL配置项。
1. 序列化器
序列化类的功能
:进行序列化和反序列化。
作用
:
1)进行数据序列化操作(将对象转成python字典)
2)进行数据反序列化操作
-
数据校验
-
数据保存(新增和更新)
定义序列化器类
:
from rest_framework import serializers
# serializers.Serializer:定义任何序列化器类时,都可以直接继承于Serializer
# serializers.ModelSerializer:如果定义的序列化器类针对的是一个模型类,可以直接继承ModelSerializer
class User(object):
def __init__(self, username, age):
self.username = username
self.age = age
class UserSerializer(serializers.Serializer):
"""序列化器类"""
# 序列化器字段 = serializers.字段类型(选项参数)
username = serializers.CharField()
age = serializers.IntegerField()
if __name__ == '__main__':
user = User('smart', 18)
# {
# "username": "smart",
# "age": 18
# }
serializer = UserSerializer(user)
# 获取序列化之后的字典数据
serializer.data
2. 序列化器-序列化
1)序列化单个对象
book = BookInfo.objects.get(id=1)
serializer = BookInfoSerializer(book)
serializer.data
2)序列化多个对象
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True)
serializer.data
3)关联对象的嵌套序列化
# 1. 将关联对象序列化为关联对象主键 serializers.PrimaryKeyRelatedField
# 2. 使用指定的序列化器将关联对象进行序列化
# 3. 将关联对象序列化为关联对象模型类__str__方法返回值 serializers.StringRelatedField
# 注意: 如果关联对象有多个,在序列化器类中定义对应字段时需要指定many=True
3. 序列化器-反序列化
1)反序列化之数据校验
data = {'btitle': 'python'}
serializer = BookInfoSerializer(data=data)
# 调用is_valid方法进行数据验证
serializer.is_valid()
# 如果验证失败,获取失败错误提示信息
serializer.errors
# 获取验证之后的数据
serializer.validated_data
# 补充验证行为:
# 1. 给对应字段指定validators参数
# 2. 在序列化器类中定义针对某个字段内容校验方法validate_<field_name>
# 3. 如果校验时需要结合多个字段的内容,在序列化器类中定义validate
2)反序列化之数据保存(新增或更新)
# 反序列化数据校验成功之后,进行数据保存
serializer.save()
# 调用序列化器类中create方法
data = {'btitle': 'python'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid()
serializer.save()
# 调用序列化器类中update方法
book = BookInfo.objects.get(id=1)
data = {'btitle': 'python'}
serializer = BookInfoSerializer(book, data=data)
serializer.is_valid()
serializer.save()
# 注意: Serializer类中create和update没有进行实现,需要自己进行实现。
4. 使用Serializer改写Django自定义RestAPI接口
将序列化和反序列化部分代码使用序列化器完成。
5. APIView视图类&Request对象&Response对象
1)APIView视图类
a)APIView是DRF框架中所有视图类的父类。
b)继承自APIView之后,处理函数中的request参数不再是Django原始的HttpRequest对象,而是由DRF框架封装的Request类的对象。
c)进行异常处理。
d)认证&权限&限流。
2)Request类
属性 | 说明 |
---|---|
request.data | 包含传递的请求体数据(比如之前的request.body和request.POST),并且已经转换成了字典或类字典类型。 |
request.query_params | 包含查询字符串参数(相当于之前的request.GET) |
3)Response类
通过Response返回响应数据时,会根据前端请求头中的Accept
转化成对应的响应数据类型,仅支持json和html,默认返回json。
4)补充
类视图对象self.kwargs
保存这从url地址中提取的所有命名参数。
6. 使用APIView改写Django自定义RestAPI接口
将获取参数以及响应部分代码进行改写。
7. GenericAPIView视图类
1)APIView类的子类,封装了操作序列化器和操作数据库的方法。
2)过滤&分页。
属性:
serializer_class: 指定视图使用的序列化器类
queryset: 指定视图使用的查询集
方法:
get_serializer_class: 返回当前视图使用的序列化器类
get_serializer: 创建一个序列化器类的对象
get_queryset: 获取当前视图使用的查询集
get_object: 获取单个对象,默认根据主键进行查询
其他功能
1)认证&权限
2)限流
控制用户访问API接口的频率。
针对匿名用户和认证用户分别进行限流。
# 限流(针对匿名用户和认证用户分别进行限流控制)
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle', # 针对匿名用户
'rest_framework.throttling.UserRateThrottle' # 针对认证用户
),
# 限流频次设置
'DEFAULT_THROTTLE_RATES': {
'user': '5/minute', # 认证用户5次每分钟
'anon': '3/minute', # 匿名用户3次每分钟
},
针对匿名用户和认证用户统一进行限流。
# 限流(针对匿名用户和认证用户进行统一限流控制)
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '5/minute',
'upload': '3/minute',
},
3)过滤&排序
4)分页
两种分页方式PageNumberPagination和LimitOffsetPagination。
使用PageNumberPagination分页时,获取分页数据时可以通过page传递页码参数。如果想要分页时指定页容量,需要自定义分页类。
class StandardResultPagination(PageNumberPagination):
# 默认页容量
page_size = 3
# 指定页容量参数名称
page_size_query_param = 'page_size'
# 最大页容量
max_page_size = 5
使用LimitOffsetPagination分页时,获取分页数据时可以传递参数offset(偏移量)和limit(限制条数)。
注:如果使用的全局分页设置,某个列表视图如果不需要分页,直接在视图类中设置pagination_class = None
。
5)异常
DRF自带异常处理功能,可以对某些特定的异常进行处理并返回给客户端组织好的错误信息。能够处理的异常如下:
APIException 所有异常的父类
ParseError 解析错误
AuthenticationFailed 认证失败
NotAuthenticated 尚未认证
PermissionDenied 权限决绝
NotFound 未找到
MethodNotAllowed 请求方式不支持
NotAcceptable 要获取的数据格式不支持
Throttled 超过限流次数
ValidationError 校验失败
可以自定义DRF框架的异常处理函数(补充一些异常处理)并指定EXCEPTION_HANDLER
配置项。
上一篇: django DRF 分页 UnorderedObjectListWarning: Pagination may yield inconsistent results with an unorder
推荐阅读