目录
rest_framework
它是基于Django的一种服务框架,可以帮助我们快速开发符合RESTful规范的接口框架。
功能:
1.路由
2.视图
3.版本
4.认证
5.权限
6.频率
7.解析器
8.序列化
9.分页
10.渲染器
在setting中配置,rest_framework实质上是一个app,需要注册才可以使用
1. rest_framework框架的封装规范
from rest_framework.views import APIView //视图
from rest_framework.request import Request //请求
from rest_framework.response import Response //响应
from rest_framework.exceptions import APIException //异常
from rest_framework.pagination import PageNumberPagination //分页
from rest_framework.settings import APISettings //设置settings
from rest_framework.parsers import JSONParser //解析
from rest_framework.filters import OrderingFilter //筛选
drf框架自定义配置
cbv中的类直接继承APIView
class BookAPIView(APIView):
pass
在settings中自定义,里面可以设置相应的
REST_FRAMEWORK = {
}
2. APIView
csrf验证不限制
原生django受csrf限制,而drf不受csrf认证限制
# django 的视图类
from django.views import View
from django.http import JsonResponse
class BookView(View):
def get(self,request,*args,**kwargs):
return JsonResponse({
'msg':'view get ok'
})
def post(self,request,*args,**kwargs):
return JsonResponse({
'msg':'view post ok'
})
# 使用APIView
from rest_framework.views import APIView
from rest_framework.response import Response
class BookAPIView(APIView):
def get(self,request,*args,**kwargs):
return Response({
'msg':'view get ok'
})
# post方法不需要注释csrf照样可以传递
def post(self,request,*args,**kwargs):
return Response({
'msg':'view post ok'
})
3. APIView生命周期
1.APIView类继承了View类,重写了as_view方法和dispatch方法
2.重写的as_view方法,主体还是View的as_view,只是在返回视图view函数地址时,局部禁用csrf认证
3.重写了dispatch方法
- 在执行请求逻辑前:请求模块(二次封装request),解析模块(三种数据包格式的数据解析)
- 在执行请求逻辑中:异常模块(执行出现任何异常交给异常处理模块处理)
- 在执行请求逻辑后:响应模块(二次封装response),渲染模块(响应的数据能被JSON和页面两种渲染)
dispatch方法:
二次封装request对象()
包含解析模块
三大认证:
(认证.权限.频率),用来替换csrf安全认证,要比csrf认证强大的多
异常模块:
处理请求异常通知,所有的API类异常都交由它处理self.handle_exception(exc)
二次封装response
处理了结果渲染,包含许多渲染模块
-
启动django项目
-
加载settings.py文件
-
读取models.py文件
-
加载views.py文件
-
加载urls.py文件
-
执行urls.py文件
url(r'^book/(?P<pk>d+)/$',views.BookAPIView.as_view()) 执行views.BookAPIView.as_view()函数方法
3.1 请求模块
-
将wsgi的request对象转化成drf的Request类的对象
-
封装后的request对象完全兼容wsgi的request对象,并且将原request保存在新request._request中
-
重新格式化请求数据存放位置
拼接参数:
request.query_params
数据包参数:
request.data
print(request._request.method) # 在内部将wsgi的request赋值给了request._request
print(request.method) # 就是通过__getattr__走的是request._request.method
print(request.query_params) # 走的是方法属性,就是给request._request.GET重新命名
print(request.data) #走的是方法属性,依赖于request._full_data
3.2 解析模块
只处理数据包参数
json // 'rest_framework.parsers.JSONParser',
urlencoded // 'rest_framework.parsers.FormParser',
form-data // 'rest_framework.parsers.MultiPartParser',
-
全局配置所有视图类的解析方式,解析配置可以配置三种
-
局部配置当前视图类的解析方式,解析配置可以配置三种
-
配置的查找顺序: 局部(视图类的类属性) => 全局(settings文件的drf配置) => 默认(drf的默配置)
注: 该模块了解,但是全局局部配置是重点
局部配置
在views中设置
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookAPIView(APIView):
parser_classes = [JSONParser,FormParser,MultiPartParser]
def get(self,request,*args,**kwargs):
pass
def post(self,request,*args,**kwargs):
pass
全局配置
在settings中配置
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
}
默认配置
drf自身的设置
在APIView类中的rest_framework.settings.APISettings
3.3 响应模块
data: 响应数据
status: 响应的网络状态码
---------------------------------------------------------
template_name: drf完成前后台不分离返回页面,但是就不可以返回data(不需要了解)
headers: 响应头,一般不规定,走默认
exception: 一般异常响应,会将其设置成true,默认为False(不设置也没事)
content_type: 默认就是application/json,不需要处理
代码
# 响应模块状态码
from rest_framework import status
class BookAPIView(APIView):
# 响应模块可以自定义返回的数据
def get(self,request,*args,**kwargs):
response = Response(
data={
'msg':'apiview get ok'
},
status=status.HTTP_404_NOT_FOUND
)
3.4 渲染模块(了解)
Postman请求结果是json,浏览器请求结果是页面
可以全局与局部配置
'rest_framework.renderers.JSONRenderer', // 渲染json
'rest_framework.renderers.BrowsableAPIRenderer', // 渲染浏览器界面,项目上线尽量关闭
全局配置
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
局部配置
# 渲染模块
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookAPIView(APIView):
# 局部配置渲染类,只适用当前视图类
renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
3.5 异常模块
源码分析
# 异常模块:APIView类的dispatch方法中
response = self.handle_exception(exc) # 点进去
# 获取处理异常的句柄(方法)
# 一层层看源码,走的是配置文件,拿到的是rest_framework.views的exception_handler
# 自定义:直接写exception_handler函数,在自己的配置文件配置EXCEPTION_HANDLER指向自己的
exception_handler = self.get_exception_handler()
# 异常处理的结果
# 自定义异常就是提供exception_handler异常处理函数,处理的目的就是让response一定有值
response = exception_handler(exc, context)
自定义异常处理
首先在settings文件中设置
REST_FRAMEWORK = {
# 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
# 配置自定义的报错函数路径
'EXCEPTION_HANDLER': 'api.exception.exception_handler',
}
需要重写exception_handle方法
,并使用系统默认的处理函数
# 自定义报错的界面
# 一定要在settings文件中将异常模块配置自己的异常处理函数
from rest_framework.response import Response
# 导入异常模块处理的函数,并起了个别名
from rest_framework.views import exception_handler as drf_exception_handler
def exception_handler(exc,content):
# 获取异常模块处理过的异常信息
response = drf_exception_handler(exc,content)
# 拼接报错信息
detail = '%s - %s - %s' % (content.get('view'),content.get('request').menthod,exc)
# 如果没有信息,就是服务端错误
if not response:
response = Response({'detail':detail})
else:
response.data = {'detail':detail}
# 核心: 要将response.data.get('detail') 信息记录到日志文件
print( response.data.get('detail'))
return response
代码
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from rest_framework import status
def exception_handler(exc, context):
# 1.先让drf的exception_handler做基础处理,拿到返回值
# 2.若有返回值则drf处理了,若返回值为空说明drf没处理,需要我们手动处理
response = drf_exception_handler(exc, context)
print(exc) # 错误内容 'NoneType' object has no attribute 'title'
print(context)
# {'view': <api.views.Book object at 0x000001BBBCE05B00>, 'args': (), 'kwargs': {'pk': '3'}, 'request': <rest_framework.request.Request object at 0x000001BBBCF33978>}
print(response)
# 返回值为空,做二次处理
if response is None:
print('%s - %s - %s' % (context['view'], context['request'].method, exc))
# <api.views.Book object at 0x00000242DC316940> - GET - 'NoneType' object has no attribute 'title'
return Response({
'detail': '服务器错误'
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True)
return response