07 DRF-版本
版本,在请求中携带版本号,便于后续API的更新迭代。
http://www.5xclass/api/v1/info
http://www.5xclass/api/v2/info
在restful规范中要去,后端的API中需要体现版本。
1 GET参数传递

# settings.py
REST_FRAMEWORK = {
"VERSION_PARAM": "v", # url中版本key
"DEFAULT_VERSION": "v1", # 不输入版本,默认为v1
"ALLOWED_VERSIONS": ["v1", "v2", "v3"], # 版本的合法性
"DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.QueryParameterVersioning" # 全局版本类
}
2 url反向生成 + 版本
分析源码
class BaseVersioning:
default_version = api_settings.DEFAULT_VERSION
allowed_versions = api_settings.ALLOWED_VERSIONS
version_param = api_settings.VERSION_PARAM
def determine_version(self, request, *args, **kwargs):
msg = '{cls}.determine_version() must be implemented.'
raise NotImplementedError(msg.format(
cls=self.__class__.__name__
))
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
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):
# /home/?version=v1
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
# 反向生成 + 版本
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
# 最终调用Django的reverse
url = super().reverse(
viewname, args, kwargs, request, format, **extra
)
if request.version is not None:
return replace_query_param(url, self.version_param, request.version)
return url
class APIView(View):
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
def determine_version(self, request, *args, **kwargs):
if self.versioning_class is None:
return (None, None)
scheme = self.versioning_class() # versioning_class
#( 版本,版本类的对象)
return (scheme.determine_version(request, *args, **kwargs), scheme)
def initial(self, request, *args, **kwargs):
# 版本的处理
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
self.initial(request, *args, **kwargs) # 这里处理
# Get the appropriate handler method
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):
# 配置文件 VERSION_PARAM=version
# http://127.0.0.1:8001/home/?version=v1 --> request.version
versioning_class = QueryParameterVersioning
def get(self, request):
print(request.version)
print(request.versioning_scheme)
self.dispatch
return Response({"code": 1000, "data": 'xxx'})

3 URL中版本的传递

4 请求头中传递


浙公网安备 33010602011771号