下面是关于drf框架中的版本控制,怎么获取版本
class HomeView(APIView):
versioning_class = QueryParameterVersioning
def get(self,request):
return Response("...")
关于django的版本控制流程
首先我们进入dispatch方法,这里是url渲染的开端(其他文章都有提及,这里不在此赘述)
然后进入到inital方法里面
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
# Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
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)
在第12行这里便是关于我们的版本控制的相关代码,我们进去看看
def determine_version(self, request, *args, **kwargs):
"""
If versioning is being used, then determine any API version for the
incoming request. Returns a two-tuple of (version, versioning_scheme)
"""
if self.versioning_class is None:
return (None, None)
scheme = self.versioning_class()
return (scheme.determine_version(request, *args, **kwargs), scheme)
这里的代码很短,显而易见,如果我们不定义versioning_class,那么他会返回none,也就是不会有什么版本控制的作用,当我们定义了这个变量,那么他会实例化这个变量,并且返回这个对象的determine_version方法的返回值,和这个对象,那么在我们的代码中就是相当于实例化
QueryParameterVersioning对象,那么我们进去这个对象
class QueryParameterVersioning(BaseVersioning):
"""
GET /something/?version=0.1 HTTP/1.1
Host: example.com
Accept: application/json
"""
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
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
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
我们看这个determine_version这个方法,第一行就说明,他会从请求头中回去我们的定义的version_param,既然这个类中没有定义,那我们就去父类中观看一下
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))
从前四行可以看到,这些参数我们可以配置在settings文件中,例如
REST_FRAMEWORK={
'VERSION_PARAM':'version',
'DEFAULT_VERSION':'v1'
}
这里我们就默认查找的参数是version,默认的version为v1(这样我在请求的时候,如果url中没有version,那么就默认传入的版本是v1),我们可以再request.version中找到这个version
除此之外,这里还有个allow_version,我们可以再settings文件中配置,如果version在这里面,那么就可以正常访问,如果不在,那么就会报错,报错的信息就是上面的invalid_version_message = _('Invalid version in query parameter.')可以根据下文重写类来实现自定义报错,如下
class HomeView(APIView):
class QueryParameterVersioning(BaseVersioning):
"""
GET /something/?version=0.1 HTTP/1.1
Host: example.com
Accept: application/json
"""
invalid_version_message = ('超出范围.') # 修改这里
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
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
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
versioning_class = QueryParameterVersioning
def get(self,request):
self.dispatch()
print(request.version)
return Response("...")