提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
在restful规范中要求,后端的API中需要体现版本。后端传递版本信息的方式主要有以下三种,其中URL中传递参数使用相对较多。
- GET中传递参数
- URL中传递参数【常用】
- 请求头中传递参数
1、GET中传递参数
1.1 源码执行流程图
1.2 源码
1.2.1 QueryParameterVersioning(BaseVersioning)、BaseVersioning
class BaseVersioning:
default_version = api_settings.DEFAULT_VERSION
allowed_versions = api_settings.ALLOWED_VERSIONS # 配置文件配置的允许版本列表
version_param = api_settings.VERSION_PARAM # 默认是version
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
# 反向生成url,传入viewname和reqeust
return _reverse(viewname, args, kwargs, request, format, **extra)
def is_allowed_version(self, version):
if not self.allowed_versions:
return True
return ((version is not None and version == self.default_version) or
(version in self.allowed_versions)) # 结果为布尔值
class QueryParameterVersioning(BaseVersioning):
invalid_version_message = _('Invalid version in query parameter.')
def determine_version(self, request, *args, **kwargs):
version = request.query_params.get(
self.version_param,
self.default_version
)
if not self.is_allowed_version(version):
raise exceptions.NotFound(self.invalid_version_message)
return version
1.2.2 HomeView(APIView)、APIView(View)
class APIView(View):
def determine_version(self, request, *args, **kwargs):
if self.versioning_class is None:
return (None, None)
scheme = self.versioning_class() # 类对象
# (v1, <rest_framework.versioning.URLPathVersioning object at 0x0000023A92344820>)
return (scheme.determine_version(request, *args, **kwargs), scheme)
def initial(self, request, *args, **kwargs):
# 获取version及scheme,并赋值给request.version, request.versioning_scheme
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
def dispatch(self, request, *args, **kwargs):
# 第一步:封装request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
try:
self.initial(request, *args, **kwargs)
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
class HomeView(APIView):
versioning_class = QueryParameterVersioning
# versioning_class = URLPathVersioning
# versioning_class = AcceptHeaderVersioning
def get(self, request, *args, **kwargs):
print(request.version)
print(request.versioning_scheme)
# 反向生成url
print(request.versioning_scheme.reverse(viewname='hh', request=request))
return Response('ok')
2、URL中传递参数【常用】
源码执行流程及源码不再详述。
3、请求头中传递参数
源码执行流程及源码不再详述。
4、反向生成URL
在每个版本处理的类中还定义了reverse
方法,是用来反向生成URL并携带相关的的版本信息用的。
以URLPathVersioning(BaseVersioning)为例,源码分析如下:
class URLPathVersioning(BaseVersioning):
# 注意:reverse方法须传入两个参数,viewname,request
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
if request.version is not None:
kwargs = {} if (kwargs is None) else kwargs
kwargs[self.version_param] = request.version
return super().reverse(
viewname, args, kwargs, request, format, **extra
)