12 drf精华总结
1.restful10条规范
# 10条规范
1 数据的安全保障:url链接一般都采用https协议进行传输 注:采用https协议,可以提高数据交互过程中的安全性
2 接口特征表现,一看就知道是个api接口
- 用api关键字标识接口url:
- [https://api.baidu.com](https://api.baidu.com/)
- https://www.baidu.com/api
注:看到api字眼,就代表该请求url链接是完成前后台数据交互的
-路飞的接口:https://api.luffycity.com/api/v1/course/free/
3 多数据版本共存
- 在url链接中标识数据版本
- https://api.baidu.com/v1
- https://api.baidu.com/v2
注:url链接中的v1、v2就是不同数据版本的体现(只有在一种数据资源有多版本情况下)
4 数据即是资源,均使用名词(可复数)
- 接口一般都是完成前后台数据的交互,交互的数据我们称之为资源
- https://api.baidu.com/users
- https://api.baidu.com/books
- https://api.baidu.com/book
注:一般提倡用资源的复数形式,在url链接中奖励不要出现操作资源的动词,错误示范:https://api.baidu.com/delete-user
- 特殊的接口可以出现动词,因为这些接口一般没有一个明确的资源,或是动词就是接口的核心含义
- https://api.baidu.com/place/search
- https://api.baidu.com/login
5 资源操作由请求方式决定(method)
- 操作资源一般都会涉及到增删改查,我们提供请求方式来标识增删改查动作
- https://api.baidu.com/books - get请求:获取所有书
- https://api.baidu.com/books/1 - get请求:获取主键为1的书
- https://api.baidu.com/books - post请求:新增一本书书
- https://api.baidu.com/books/1 - put请求:整体修改主键为1的书
- https://api.baidu.com/books/1 - patch请求:局部修改主键为1的书
- https://api.baidu.com/books/1 - delete请求:删除主键为1的书
6 过滤,通过在url上传参的形式传递搜索条件
- https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
- https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
- https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
- https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
- https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
7 响应状态码
7.1 正常响应
- 响应状态码2xx
- 200:常规请求
- 201:创建成功
7.2 重定向响应
- 响应状态码3xx
- 301:永久重定向
- 302:暂时重定向
7.3 客户端异常
- 响应状态码4xx
- 403:请求无权限
- 404:请求路径不存在
- 405:请求方法不存在
7.4 服务器异常
- 响应状态码5xx
- 500:服务器异常
8 错误处理,应返回错误信息,error当做key
{
error: "无权限操作"
}
9 返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档
10 需要url请求的资源需要访问资源的请求链接
# Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么
{
"status": 0,
"msg": "ok",
"results":[
{
"name":"肯德基(罗餐厅)",
"img": "https://image.baidu.com/kfc/001.png"
}
...
]
}
2 django上写符合restful规范的接口
3 drf写接口
4 APIView--》继承了原生View---》get,post方法
-(为什么get请求来了,就会执行get方法:原生View的dispatch控制的)
-路由配置:视图类.as_view()---->view(闭包函数)的内存地址
-请求来了,就会执行view(requst,分组分出的字段,默认传的字段)---》self.dispatch()-->处理的
-APIView重写了dispatch:包装了request对象,解析器,分页,三大认证,响应器,全局异常,去掉了csrf
5 Request对象
request._request,request.data,重写了__getattr__,request.method-->去原生request中拿
-前端传过来的数据从那取?
-地址栏里:request.GET/query_params
-请求体中的数据:request.data/POST(json格式解释不了)---》request.body中取
-请求头中数据:request.META.get("HTTP_变成大写")
6 Response对象
封装了原生的HttpResponse,Response(data,headers={},status=1/2/3/4/5开头的)
7 自定义Response对象
8 序列化类
-Serializer
-写字段,字段名要跟表的字段对应,想不对应(source可以修改),有属性,read_only,max_len...
-SerializerMethodField必须配套一个get_字段名,返回什么,前台就看到什么
-ModelSerializer
-class Meta:
表对应
取出的字段(__all__,列表)
排除的字段(用的很少)
extra_kwargs会给字段的属性
-重写某个字段
password=serializers.SerializerMethodField()
def get_password(self,instance):
return "***"
-校验:字段自己的校验,局部钩子,全局钩子
-只要序列化类的对象执行了is_valiad(),这些钩子都会走,可以再钩子里写逻辑
-在表模型(model)中写方法,可以在上面取出的字段中直接写,不参与反序列化
-序列化多条(many=True):本质,ListSerializer内部套了一个个的serializer对象
-重写ListSerializer,让序列化对象和自己写的ListSerializer对应上(了解)
-序列化类(instance,data,many,context={requtst:request})
-视图函数中给序列化对象传递数据,使用context,传回来,放进去直接使用序列化对象.context.get()
9 视图
-两个视图基类 APIView,GenericAPIView(继承APIView):涉及到数据库和序列化类的操作,尽量用GenericAPIView
-5个视图扩展类(父类都是object)
CreateModelMixin:create
DestroyModelMixin:destory
ListModelMixin
RetrieveModelMixin
UpdateModelMixin
-9个视图子类(GenericAPIView+上面5个视图扩展类中的一个或多个)
RetrieveUpdateDestroyAPIView
CreateAPIView
RetrieveAPIView
DestroyAPIView
RetrieveUpdateAPIView
ListCreateAPIView
UpdateAPIView
ListAPIView
RetrieveDestroyAPIView
-视图集
-ModelViewSet:5大接口都有了
-ReadOnlyModelViewSet:获取一条和获取多条的接口
-GenericViewSet:ViewSetMixin+GenericAPIView
ViewSet:ViewSetMixin+APIView
ViewSetMixin:类重写了as_view,路由配置就变样了
10 路由
-基本配置:跟之前一样
-有action的:必须继承ViewSetMixin
-自动生成:DefaultRouter和SimpleRouter
-导入,实例化得到对象,注册多个,对象.urls(自动生成的路由)
-路由相加urlpatterns+=router.urls/include:path('', include(router.urls))
-视图类中自己定义的方法,如何自动生成路由
-在自己定义的方法上加装饰器(action)
-两个参数methods=[GET,POST],表示这两种请求都能接受
-两个参数detail=True,表示生成带pk的连接
11 三大认证
-认证组件:校验用户是否登录
-写一个认证类,继承BaseAuthentication,重写authenticate,内部写认证逻辑,认证通过返回两个值,第一个是user,认证失败,抛去异常
-全局使用,局部使用,局部禁用
-权限:校验用户是否有权限进行后续操作
-写一个类,继承BasePermission,重写has_permission,True和False
-全局使用,局部使用,局部禁用
-频率:限制用户访问频次
-写一个类,继承SimpleRateThrottle,重写get_cache_key,返回什么,就以谁做限制,scop=luffy字段,需要跟setting中的key对应 luffy:3/h(一小时访问三次)
-全局配置,局部配置,局部禁用
-需求:发送短信验证码的接口,一分钟只能发送一次,局部使用,配在视图类上
12 解析器
前端传的编码格式,能不能解析(默认三种全配了,基本不需要改),可能你写了个上传文件接口,局部配置一下,只能传form-data格式 局部使用:MultiPartParser
13 响应器
响应的数据,是json格式还是带浏览器的那种(不需要配)
14 过滤器
借助于第三方django-filter
-注册应用
-setting中配置DjangoFilterBackend或者局部配置
-filter_fields = ('age', 'sex')
15 排序
-全局或者局部配置rest_framework.filters.OrderingFilter
-视图类中配置: ordering_fields = ('id', 'age')
16 分页
-使用:
继承了APIView的视图类中使用
page=Mypage()
# 在数据库中获取分页的数据
page_list=page.paginate_queryset(queryset对象,request,view=self)
# 对分页进行序列化
ser=BookSerializer1(instance=page_list,many=True)
# return Response(ser.data)
继承了视图子类的视图中使用
pagination_class = PageNumberPagination(配置成自己重写的,可以修改字段)
-CursorPagination
cursor_query_param:默认查询字段,不需要修改
page_size:每页数目
ordering:按什么排序,需要指定
-LimitOffsetPagination
default_limit 默认限制,默认值与PAGE_SIZE设置一直
limit_query_param limit参数名,默认’limit’
offset_query_param offset参数名,默认’offset’
max_limit 最大limit限制,默认None
-PageNumberPagination:最常用的,需要在setting中配置page_size,四个参数
page_size 每页数目
page_query_param 前端发送的页数关键字名,默认为”page”
page_size_query_param 前端发送的每页数目关键字名,默认为None
max_page_size 前端最多能设置的每页数量
17 全局异常
-写一个方法
def exception_handler(exc, context):
# 走drf原来的异常,原理异常有一些处理
response = drf_exception_handler(exc, context)
# 我们自己处理,drf没有处理,丢给django的异常
if response is None:
if isinstance(exc, DatabaseError):#处理了一下数据库错误
response = Response({'detail': '数据库错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
else:#其他异常
response = Response({'detail': '未知错误'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return response
-配置文件中配置(以后所有drf的异常,都会走到这里)
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
18 jwt
-是什么json web token 新的认证方式
-三段:头,荷载(用户信息),签名
-使用:最简单方式(在路由中配置)
-path('login/', obtain_jwt_token),
-自定制:
多方式登录,手动签发token(两个方法)
-自定制基于jwt的认证类
-取出token
-调用jwt提供的解析出payload的方法(校验是否过期,是否合法,如果合法,返回荷载信息)
-转成user对象
-返回
-19 RBAC:基于角色的权限控制(django默认的auth就是给你做了这个事),公司内部权限管理
对外的权限管理就是用三大认证
-用户表
-用户组表
-权限表
-用户对用户组中间表
-用户组对权限中间表
-用户对权限中间表