07 DRF-版本

版本,在请求中携带版本号,便于后续API的更新迭代。

http://www.5xclass/api/v1/info
http://www.5xclass/api/v2/info

在restful规范中要去,后端的API中需要体现版本。


1 GET参数传递

image

# settings.py

REST_FRAMEWORK = {
    "VERSION_PARAM": "v",  # url中版本key
    "DEFAULT_VERSION": "v1",  # 不输入版本,默认为v1
    "ALLOWED_VERSIONS": ["v1", "v2", "v3"],  # 版本的合法性
    "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.QueryParameterVersioning"  # 全局版本类
}

2 url反向生成 + 版本

分析源码
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))


class QueryParameterVersioning(BaseVersioning):
    invalid_version_message = _('Invalid version in query parameter.')

    def determine_version(self, request, *args, **kwargs):
    	# /home/?version=v1
        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):
        # 最终调用Django的reverse
        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


class APIView(View):
	versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

    def determine_version(self, request, *args, **kwargs):
        if self.versioning_class is None:
            return (None, None)
        scheme = self.versioning_class()  # versioning_class
        #( 版本,版本类的对象)
        return (scheme.determine_version(request, *args, **kwargs), scheme)


    def initial(self, request, *args, **kwargs):
        # 版本的处理
        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)


    def dispatch(self, request, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            self.initial(request, *args, **kwargs)  # 这里处理

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed

            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response



class HomeView(APIView):
    # 配置文件 VERSION_PARAM=version
    # http://127.0.0.1:8001/home/?version=v1  --> request.version
    versioning_class = QueryParameterVersioning

    def get(self, request):
        print(request.version)
        print(request.versioning_scheme)
        self.dispatch
        return Response({"code": 1000, "data": 'xxx'})

image


3 URL中版本的传递

image


4 请求头中传递

image

posted @ 2022-10-19 10:42  角角边  Views(23)  Comments(0)    收藏  举报