流程:
- 执行self.initial(request, *args, **kwargs) 方法
- 获取版本version, scheme = self.determine_version(request, *args, **kwargs)
settings 文件全局配置:
'DEFAULT_VERSION': 'v1', #默认版本号
'VERSION_PARAM': 'version', #指定参数
'ALLOWED_VERSIONS': ['v1', 'v2'], #允许访问的版本号
自定义:
class Myversion(BaseVersioning):
def determine_version(self, request, *args, **kwargs):
# version = request._request.GET.get("version")
version = request.query_params.get("version")
return (version, ) # scheme 版本对象
# determine_version返回后,设置到version, versioning_scheme
# version, scheme = self.determine_version(request, *args, **kwargs)
# request.version, request.versioning_scheme = version, scheme赋值
# request.query_params(封装方法) == request._request.GET
class Myview(APIView):
versioning_class = Myversion #指定版本获取类
def get(self, request, *args, **kwargs):
print(request.version) #直接获取值
print(request.versioning_scheme)
return Response("ok")
内置方法:
- QueryParameterVersioning 查询字符串方式
def determine_version(self, request, *args, **kwargs):
version = request.query_params.get(self.version_param, self.default_version)
# version_param 为settings中的 VERSION_PARAM
# default_version 为settings中的 DEFAULT_VERSION
# is_allowed_version 判断是否在 ALLOWED_VERSIONS列表中
if not self.is_allowed_version(version):
raise exceptions.NotFound(self.invalid_version_message)
return version
- URLPathVersioning通过路由变量方式
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
url(r'^(?P<version>[v1|v2]+)/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail')
]
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
- HostNameVersioning 通过子域名的方式
"""
GET /something/ HTTP/1.1
Host: v1.example.com
Accept: application/json
"""
hostname_regex = re.compile(r'^([a-zA-Z0-9]+).[a-zA-Z0-9]+.[a-zA-Z0-9]+$')
invalid_version_message = _('Invalid version in hostname.')
def determine_version(self, request, *args, **kwargs):
hostname, separator, port = request.get_host().partition(':')
match = self.hostname_regex.match(hostname)
if not match:
return self.default_version
version = match.group(1) #获取版本号
if not self.is_allowed_version(version):
raise exceptions.NotFound(self.invalid_version_message)
return version
- 其它NamespaceVersioning(基于路由系统分发) , AcceptHeaderVersioning(基于Accept请求头)
对于内置的rest_framework reverse函数:
print(request.versioning_scheme.reverse(viewname='Myview',request=request)) #反向生成url
#不用指定版本号是因为:重写的reverse函数已经把版本号赋值给kwargs:
# if request.version is not None:
# kwargs = {} if (kwargs is None) else kwargs
# kwargs[self.version_param] = request.version
print(reverse(viewname='Myview', kwargs={'version': 'v2'})) #原生的reverse函数 需指定版本号
'''
output:
http://127.0.0.1:8000/v1/Myview/
/v2/Myview/
'''