源码流程
# 第一步:请求到来先执行APIView.dispatch
APIView.dispatch(self, request, *args, **kwargs)
# 第二步:APIView.dispatch指向APIView.initial
APIView.initial(request, *args, **kwargs)
# 第三步:APIView.initial中指向APIView.determine_version,
# 在APIView.determine_version内部执行了配置的versioning_class的determine_version方法
version, scheme = self.determine_version(request, *args, **kwargs)
APIView.determine_version(self, request, *args, **kwargs):
scheme = self.versioning_class()
return (scheme.determine_version(request, *args, **kwargs), scheme)
URLPathVersioning.determine_version(self, request, *args, **kwargs):
return version
# 第四步:将版本号和versioning_class的实例封装到request中
request.version, request.versioning_scheme = version, scheme
# 第五步:使用
class QueryParamVersionView(APIView):
versioning_class = QueryParameterVersioning # 配置版本类
def get(self, request, *args, **kw):
print(request.version) # 接收到的版本号
print(request.versioning_scheme) # 版本类的实例
return Response('...')
使用
这里列举了三种常用的版本方式
settings.py
REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1', # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
'VERSION_PARAM': 'v' # URL中获取值的key
}
urls.py
urlpatterns = [
url(r'^queryparam/', views.QueryParamVersionView.as_view(), name='queryparam'),
url(r'^(?P<v>[v1|v2]+)/urlpath/', views.URLPathVersionView.as_view(), name='urlpath'),
url(r'^hostname/', views.HostNameVersion.as_view(), name='hostname'),
]
views.py
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.versioning import QueryParameterVersioning, URLPathVersioning, HostNameVersioning
class QueryParamVersionView(APIView):
versioning_class = QueryParameterVersioning # 基于url的get传参方式 http://127.0.0.1:8000/api/queryparam/?v=v2
def get(self, request, *args, **kw):
print(request.version) # 接收到的版本号
print(request.versioning_scheme) # 版本类的实例
# 版本类的reverse方法只能反向生成当前版本的url
reverse_url = request.versioning_scheme.reverse('queryparam', request=request)
print(reverse_url)
# django的reverse方法可以反向生成任意版本的url
from django.urls import reverse
from urllib.parse import urlencode
base_url = reverse('queryparam')
reverse_url = "%s?%s" % (base_url, urlencode({'v': 'v1'}))
print(reverse_url)
return Response('...')
class URLPathVersionView(APIView):
versioning_class = URLPathVersioning # 基于url的正则方式 http://127.0.0.1:8000/api/v1/urlpath/
def get(self, request, *args, **kw):
print(request.version) # 接收到的版本号
print(request.versioning_scheme) # 版本类的实例
# 版本类的reverse方法只能反向生成当前版本的url
reverse_url = request.versioning_scheme.reverse('urlpath', request=request)
print(reverse_url)
# django的reverse方法可以反向生成任意版本的url
from django.urls import reverse
reverse_url = reverse('urlpath', kwargs={'v': 'v2'})
print(reverse_url)
return Response('...')
class HostNameVersion(APIView):
versioning_class = HostNameVersioning # 基于主机名方法 http://v1.example.com:8000/api/hostname/
def get(self, request, *args, **kw):
print(request.version) # 接收到的版本号
print(request.versioning_scheme) # 版本类的实例
# 版本类的reverse方法只能反向生成当前版本的url
reverse_url = request.versioning_scheme.reverse('hostname', request=request)
print(reverse_url)
# django的reverse方法可以反向生成任意版本的url
from django.urls import reverse
base_url = reverse('hostname')
reverse_url = "http://%s.example.com:8000/api/hostname/" % 'v1'
print(reverse_url)
return Response('...')
全局使用
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
'DEFAULT_VERSION': 'v1',
'ALLOWED_VERSIONS': ['v1', 'v2'],
'VERSION_PARAM': 'version'
}
网友评论