04 drf源码剖析之版本
2024-10-09 10:11:18
04 drf源码剖析之版本
1. 版本简述
API版本控制使您可以更改不同客户端之间的行为。REST框架提供了许多不同的版本控制方案。
版本控制由传入的客户端请求确定,并且可以基于请求URL或基于请求标头。
启用API版本控制后,该
request.version
属性将包含一个字符串,该字符串与传入客户端请求中请求的版本相对应。默认情况下,版本控制未启用,并且
request.version
将始终返回None
。
2. 版本使用
settings配置文件
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
'ALLOWED_VERSIONS':['v1','v2'], }
路由
# 路由分发
urlpatterns = [
url(r'^api/(?P<version>\w+)/', include('api.urls')),
] # 子路由
urlpatterns = [
url(r'^order/$', views.OrderView.as_view()),
]
通过request.version可以取值
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request class OrderView(APIView):
def get(self,request,*args,**kwargs):
print(request.version)
print(request.versioning_scheme)
return Response('...') def post(self,request,*args,**kwargs):
return Response('post')
3.源码剖析
请求到来执行dispatch方法
class APIView(View):
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS def dispatch(self, request, *args, **kwargs): # 第一步
self.args = args
self.kwargs = kwargs """
request = 生成了一个新的request对象,此对象的内部封装了一些值。
request = Request(request)
- 内部封装了 _request = 老的request
"""
request = self.initialize_request(request, *args, **kwargs)
self.request = request self.headers = self.default_response_headers # deprecate? try:
# 第二步
self.initial(request, *args, **kwargs) 执行视图函数...
执行initial方法
def initial(self, request, *args, **kwargs): # 2.1 处理drf的版本
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
...
determine_version
- versioning_class是在配置文件设置的URLPathVersioning
def determine_version(self, request, *args, **kwargs):
if self.versioning_class is None:
return (None, None)
scheme = self.versioning_class() # obj = XXXXXXXXXXXX()
return (scheme.determine_version(request, *args, **kwargs), scheme)
接着去执行URLPathVersioning对象的determine_version方法
class URLPathVersioning(BaseVersioning):
"""
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'), ]
"""
invalid_version_message = _('Invalid version in URL path.') def determine_version(self, request, *args, **kwargs):
version = kwargs.get(self.version_param, self.default_version)
if version is None:
version = self.default_version if not self.is_allowed_version(version):
raise exceptions.NotFound(self.invalid_version_message)
return version
4. 总结
- 请求过来执行dispatch方法中的initial方法中的版本处理的determine_version方法
- 找到setings配置中版本类URLPathVersioning,对其实例化,
- 执行实例化对象的determine_version方法,
- 该方法会获取路由中输入的版本信息,
- 在is_allowed_version方法中会判断url中的版本是否在settings配置设定的ALLOWED_VERSIONS列表中
- 如果在就将版本赋值给request.version,将版本类赋值给request.versioning_scheme
最新文章
- 彻底解决m2eclipse之Unable to update index for central
- OpenGL FAQ
- 框架 Onboard-引导页样式制作库
- 在laravel下關於blade模板的嘗試
- django入门记录 2
- 解决webstorm乱码
- Linux-记录一次被当肉鸡行为
- ant的那些闹挺事
- Call to undefined function imagettftext()解决方法
- Cocos2d-x 手游聊天系统需求分析
- TCP/IP详细说明--滑模、拥塞窗口、慢启动、Negle算法
- unsupported major.minor version 52.0,错误
- 7-27 Codeforces Round #499 (Div. 2)
- skywalking部署
- sqlserver记录去重
- centos7.5上一步步部署jumpserver
- Sublime Text3 3143 注册码,亲测可用!
- windows Server 2008 R2 开关机取消登录时要按Ctrl+Alt+Delete组合键登录的方法
- 抓取biqukan
- py库: Tesseract-OCR(图像文字识别)
热门文章
- python中的常用BIF
- 自动完成 APP【字典树(Trie树)+dfs】
- postman获得时间戳和md5加密的方法
- filter()函数过滤序列
- 【JMeter_06】JMeter逻辑控制器__If控制器<;If Controller>;
- Page ";页面路径"; has not been registered yet.
- 阿里巴巴--mysql中Mysql模糊查询like效率,以及更高效的写法
- CSS定位(Positioning)
- P2220 [HAOI2012]容易题【快速幂】
- .Net: C#中的委托(Delegate)和事件(Event)