基于上述分析
#2.处理版本信息 处理认证信息 处理权限信息 对用户的访问频率进行限制 self.initial(request, *args, **kwargs)
#2.1处理版本信息 #version代表版本 scheme代表版本管理的类 determine_version返回的是一个元祖 version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme
进入determine_version方法
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) """ #versioning_class = api_settings.DEFAULT_VERSIONING_CLASS #如果我们没有配置版本控制类,将不做版本控制 if self.versioning_class is None: return (None, None) #scheme就是版本控制的类 #versioning_class = api_settings.DEFAULT_VERSIONING_CLASS scheme = self.versioning_class() #返回版本 和版本控制的类 return (scheme.determine_version(request, *args, **kwargs), scheme)
scheme.determine_version的执行取决与我们所引用的版本控制类是哪一个
这里以常用的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 = [ url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'), url(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_param default_version DEFAULT_VERSION 都是在settings配置 #version_param :url中获取值的key #default_version :默认版本 #ALLOWED_VERSIONS:允许的版本 version = kwargs.get(self.version_param, self.default_version) #如果version不存在,或者version不在允许访问的版本列表中 if not self.is_allowed_version(version): #抛出异常 raise exceptions.NotFound(self.invalid_version_message) #返回版本 return version
is_allowed_version方法
#判断是否能访问当前版本 def is_allowed_version(self, version): if not self.allowed_versions: return True #version存在并且等于默认版本或者version在允许访问的版本中 #返回True or Fasle return ((version is not None and version == self.default_version) or (version in self.allowed_versions))
到这里我们获取到了具体访问的版本和控制版本的类
回到最开始
#2.1处理版本信息 #version代表版本 scheme代表版本管理的类 determine_version返回的是一个元祖 version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme
我们将version 和scheme封装在request中如果我们访问的版本符合要求我们可以通过调用
request.version, request.versioning_scheme 来获得版本号和控制版本的类
BaseVersioning所有版本控制类都要继承的基类
class BaseVersioning(object): 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 #version存在并且等于默认版本或者version在允许访问的版本中 #返回True or Fasle return ((version is not None and version == self.default_version) or (version in self.allowed_versions))