ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

drf(五)—版本控制

2022-04-07 22:01:46  阅读:137  来源: 互联网

标签:None 版本控制 self request version kwargs drf


drf(五)—版本控制

1.源码流程

与前几节的介绍相同源码入口依旧为dispatch()inital();

def initial(self, request, *args, **kwargs):
    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对象。
    request.version, request.versioning_scheme = version, scheme
    # 因此,当我们想要获取版本的时候应该可以直接去request中进行查找

    # Ensure that the incoming request is permitted
    self.perform_authentication(request)
    self.check_permissions(request)
    self.check_throttles(request)

determine_version() 函数。

def determine_version(self, request, *args, **kwargs):
    if self.versioning_class is None: 
        return (None, None)#版本控制类不存在,返回值为None
    scheme = self.versioning_class() # 实例化版本控制类的对象。
    return (scheme.determine_version(request, *args, **kwargs), scheme)
	# 返回值是两个对象,一个是执行函数,另一个是控制类的实例化对象
    '''
    	版本控制类中使用的不是列表生成式,表明版本控制类只有一个而不是多个。
 		此处表明版本控制类中需要具备determine_version()方法。
 		
 		结合上面函数猜想,返回值应该是版本与对象.
 		versioning_class指向配置文件。
    '''

image-20220407203606146

2.自定义使用

class ParamVersion(object):
    def determine_version(self, request, *args, **kwargs):
        version = request.query_params.get('version')
        return version

自定义的类中直接获取参数;

from app01.utils.version import ParamVersion
class VersionView(APIView):
    throttle_classes = []
    permission_classes = []
    authentication_classes = [] #为方便验证直接将认证功能在该函数中取消。
    versioning_class = ParamVersion #版本控制类不能使用列表,因此直接使用类名
    def get(self,request,*args,**kwargs):
        version=request.version
        print(version)
        return JsonResponse({"msg":"当前版本是%s"%(version)})

image-20220407211241476

此种方式使用较少,因为版本号通常是写在路由中而不是以参数的形式进行传播。

3.内置版本控制类

from rest_framework.versioning import URLPathVersioning,BaseVersioning

BaseVersioning类

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 from rest_framework.versioning import URLPathVersioningself.allowed_versions:
            return True
        return ((version is not None and version == self.default_version) or
                (version in self.allowed_versions))

URLPathVersioning 类

class URLPathVersioning(BaseVersioning):# 继承上述的类
        """
    To the client this is the same style as `NamespaceVersioning`.
    The difference is in the backend - this implementation uses
    Django's URL keyword arguments to determine the version.

    An example URL conf for two views that accept two different versions.

    urlpatterns = [
    	re_path(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
    	# 使用动态路由进行传参。
        re_path(r'^(?P<version>[v1|v2]+)/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail')
    ]

    GET /1.0/something/ HTTP/1.1
    Host: example.com
    Accept: application/json
    """
    
    
    
    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 reverse(self,viewname,args=None,kwargs=None, request=None, format=None, **extra):
        if request.version is not None:
            kwargs = {} if (kwargs is None) else kwargs
            kwargs[self.version_param] = request.version

        return super().reverse(
            viewname, args, kwargs, request, format, **extra
        )

内置类封装的功能已经可以满足大多数功能。

全局配置:

image-20220407214230372

默认版本号,允许的版本号,版本参数名称。

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":['app01.utils.auth.MyAuthentication',],
    "UNAUTHENTICATED_USER":None, # 匿名,request.user = None
    "UNAUTHENTICATED_TOKEN":None,
    "DEFAULT_PERMISSION_CLASSES":['app01.utils.permission.MyPermission',],
    "DEFAULT_THROTTLE_CLASSES":['app01.utils.throttle.MyThrottle',],
    	# 匿名用户不能在全局配置需要为登录功能单独添加
    "DEFAULT_THROTTLE_RATES":{
        "visit":'3/m',#一分钟三次,匿名用户
        "loginuser":'10/m',# 登录成功,一分钟10次
    },
    
   # 版本的配置直接配置即可使用内置的版本控制类。
   "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
    "DEFAULT_VERSION":'v1',
    "ALLOWED_VERSIONS":['v1','v2'], #允许的版本号
    "VERSION_PARAM":"version",# 这个参数应该和 路由中的名称相同version/
}

image-20220407214953729

继续努力,终成大器!

标签:None,版本控制,self,request,version,kwargs,drf
来源: https://www.cnblogs.com/Blogwj123/p/16114467.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有