drf 版本解析

版本

使用(局部)

  • url中写version

    url(r'^order/(?P<version>[v1|v2]+)/$', views.OrderView.as_view()),
    
    
  • 在视图中应用

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.versioning import URLPathVersioning
    
    
    class OrderView(APIView):
    
        versioning_class = URLPathVersioning	# 引用版本类
        def get(self,request,*args,**kwargs):
            print(request.version)
            print(request.versioning_scheme)
            return Response('...')
    
        def post(self,request,*args,**kwargs):
            return Response('post')
    
  • 在settings中配置

    REST_FRAMEWORK = {
        "PAGE_SIZE":2,
        "DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination",
        "ALLOWED_VERSIONS":['v1','v2'],
        'VERSION_PARAM':'version'
    }
    

使用(全局)推荐

  • url中写version

    url(r'^order/(?P<version>[v1|v2]+)/$', views.OrderView.as_view())
    
    url(r'^order/(?P<version>w+)/$', views.OrderView.as_view()),
    
  • 在视图中应用

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.versioning import URLPathVersioning
    
    
    class OrderView(APIView):
        def get(self,request,*args,**kwargs):
            print(request.version)
            print(request.versioning_scheme)
            return Response('...')
    
        def post(self,request,*args,**kwargs):
            return Response('post')
    
  • 在settings中配置

    REST_FRAMEWORK = {
    
        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
        "ALLOWED_VERSIONS":['v1','v2'],
        'VERSION_PARAM':'version'
    }
    

源码分析

class APIView(View):
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
    
	def dispatch(self, request, *args, **kwargs):
       
        # ###################### 第一步 ###########################
        """
        request,是django的request,它的内部有:request.GET/request.POST/request.method
        args,kwargs是在路由中匹配到的参数,如:
            url(r'^order/(d+)/(?P<version>w+)/$', views.OrderView.as_view()),
            http://www.xxx.com/order/1/v2/
        """
        self.args = args
        self.kwargs = kwargs

        """
        request = 生成了一个新的request对象,此对象的内部封装了一些值。
        request = Request(request)
            - 内部封装了 _request = 老的request
        """
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request

        self.headers = self.default_response_headers  # deprecate?

        try:
            # ###################### 第二步 ###########################
            self.initial(request, *args, **kwargs)

            执行视图函数。。
	
	def initial(self, request, *args, **kwargs):
       
        # ############### 2.1 处理drf的版本 ##############
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
		...
        
    def determine_version(self, request, *args, **kwargs):
        if self.versioning_class is None:
            return (None, None)
        scheme = self.versioning_class() # obj = XXXXXXXXXXXX()
        return (scheme.determine_version(request, *args, **kwargs), scheme)
        

版本类:

class URLPathVersioning(BaseVersioning):
    """
    urlpatterns = [
        url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
       
    ]
    """
    invalid_version_message = _('Invalid version in URL path.')

    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
#  ================    
    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))

流程分析:

- 请求到来时,会执行APIView类的dispatch方法,先进行属性的封装;
- 执行initial方法,里面先进行版本的处理:
- 会执行determine_version()方法,会获取versioning_class的类URLPathVersioning, 
- 实例化URLPathVersioning类,然后执行URLPathVersioning类中的determine_version()方法,
- 通过kwargs.get()获取版本信息v1,如果没有,返回None;通过kwargs.get()获取版本信息v1,如果没有,返回None;
- allowed_version获取配置中版本列表,
然后判断获取到的版本信息是否在列表中,存在,返回version。
原文地址:https://www.cnblogs.com/yzm1017/p/11945833.html