drf版本控制

2023年 10月 2日 49.7k 0

下面是关于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("...")

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论