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)将模型对象转换为前端所需的格式(序列化)。
1. Mixin扩展类
DRF提供了5个扩展类,封装了5个通用的操作流程。
类名说明ListModelMixin提供了一个list方法,封装了返回模型数据列表信息的通用流程。CreateModelMixin提供了一个create方法,封装了创建一个模型对象数据信息的通用流程。RetrieveModelMixin提供了一个retrieve方法,封装了获取一个模型对象数据信息的通用流程。UpdateModelMixin提供了一个update方法,封装了更新一个模型对象数据信息的通用流程。DestroyModelMixin提供了一个destroy方法,封装了删除一个模型对象数据信息的通用流程。2. 子类视图
为了方便我们开发RestAPI,DRF框架除了提供APIView和GenericAPIView视图类之外,还提供了一些子类视图类,这些子类视图类同时继承了GenericAPIView和对应的Mixin扩展类,并且提供了对应的请求方法。
类名说明ListAPIView1)继承自ListModelMixin和GenericAPIView。2)如果想定义一个视图只提供列出模型列表信息的接口,继承此视图类是最快的方式。CreateAPIView1)继承自CreateModelMixin和GenericAPIView。2)如果想定义一个视图只提供创建一个模型信息的接口,继承此视图类是最快的方式。RetrieveAPIView1)继承自RetrieveModelMixin和GenericAPIView。2)如果想定义一个视图只提供获取一个模型信息的接口,继承此视图类是最快的方式。UpdateAPIView1)继承自UpdateModelMixin和GenericAPIView。2)如果只想定义一个视图只提供更新一个模型信息的接口,继承此视图类是最快的方式。DestroyAPIView1)继承自DestroyModelMixin和GenericAPIView。2)如果只想定义一个视图只提供删除一个模型信息的接口,继承此视图类是最快的方式。ListCreateAPIView1)继承自ListModelMixin,CreateModelMixin和GenericAPIView。2)如果只想定义一个视图提供列出模型列表和创建一个模型信息的接口,继承此视图类是最快的方式。RetrieveUpdateAPIView1)继承自RetrieveModelMixin,UpdateModelMixin和GenericAPIView。2)如果只想定义一个视图提供获取一个模型信息和更新一个模型信息的接口,继承此视图类是最快的方式。RetrieveDestroyAPIView1)继承自RetrieveModelMixin,DestroyModelMixin和GenericAPIView。2)如果只想定义一个视图提供获取一个模型信息和删除一个模型信息的接口,继承此视图类是最快的方式。RetrieveUpdateDestoryAPIView1)继承自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 = BookInfoSerializer3. 视图集类
将操作同一资源的处理方法放在同一个类中(视图集),处理方法不要以请求方式命名,而是以对应的action命名。
list: 提供一组数据 create: 创建一条新数据 retrieve: 获取指定的数据 update: 更新指定的数据 destroy: 删除指定的数据进行url配置时需要指明请求方法和处理函数之间的对应关系。
类名说明ViewSet1)继承自ViewSetMixin和APIView。2)如果使用视图集时不涉及数据库和序列化器的操作,可以直接继承此类。GenericViewSet1)继承自ViewSetMixin和GenericAPIView。2)如果使用视图集涉及数据库和序列化器的操作,可以直接继承此类。ModelViewSet1)继承自5个Mixin扩展类和GenericViewSet。2)如果使用视图集想一次提供通用的5种操作,继承这个类是最快的。ReadOnlyModelViewSet1)继承自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.data2. 序列化器-序列化
1)序列化单个对象
book = BookInfo.objects.get(id=1) serializer = BookInfoSerializer(book) serializer.data2)序列化多个对象
books = BookInfo.objects.all() serializer = BookInfoSerializer(books, many=True) serializer.data3)关联对象的嵌套序列化
# 1. 将关联对象序列化为关联对象主键 serializers.PrimaryKeyRelatedField # 2. 使用指定的序列化器将关联对象进行序列化 # 3. 将关联对象序列化为关联对象模型类__str__方法返回值 serializers.StringRelatedField # 注意: 如果关联对象有多个,在序列化器类中定义对应字段时需要指定many=True3. 序列化器-反序列化
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. 如果校验时需要结合多个字段的内容,在序列化器类中定义validate2)反序列化之数据保存(新增或更新)
# 反序列化数据校验成功之后,进行数据保存 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配置项。