RESF framework框架-版本源码流程解析

190 阅读2分钟

1、版本

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

感激相遇 你好 我是y大壮

作者:y大壮
链接:juejin.cn/user/756923… 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

🌊🌈关于前言:

文章部分内容及图片出自网络,如有问题请与我本人联系

🌊🌈关于内容:

主要是配置settings.py版本信息,然后在参考把版本信息是反正url,还是请求头.....哪里哪里。。

1.1 自定义版本

自定义: http://127.0.0.1:8000/api/users/?version=v2

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

class UsersView(APIView):

        versioning_class = ParamVersion   # 注意这里是当个,不是列表了
        def get(self,request,*args,**kwargs):
                #version = request._request.GET.get('version')
                #print(version)
                # version = request.query_params.get('version')
                # print(version)

                print(request.version)

                return HttpResponse('用户列表')

1.2 使用自带的版本

# 使用:

配置文件:
REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',  # 版本信息
    "DEFAULT_VERSION": 'v1',  # 默认版本号,默认值为None
    "ALLOWED_VERSIONS": ['v1', 'v2'],  # 允许请求的版本号,默认值为None
    "VERSION_PARAM": 'version',  # 识别版本号参数的名称,默认值为'version'
}

路由:
urlpatterns = [ # 主路由
    url(r'^api/', include('api.urls')),
]

urlpatterns = [
    # http://127.0.0.1:8000/api/v1/users/
    # http://127.0.0.1:8000/api/v2/users/
    url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view(),name='uuu'),
]
                    
# views.py                    
class UsersView(APIView):
    permission_classes = []

    def get(self, request, *args, **kwargs):
        # 1. 获取版本  v1
        print(request.version) 
        # 2. 获取处理版本的对象 <rest_framework.versioning.URLPathVersioning object at 0x000001C3AA7D3E10>
        print(request.versioning_scheme)  
        # 3. 反向生成URL(rest framework) http://127.0.0.1:8000/api/v1/users/
        u1 = request.versioning_scheme.reverse(viewname='uuu', request=request)
        print(u1)
        # 4. 反向生成URL /api/2/users/
        u2 = reverse(viewname='uuu', kwargs={'version': 2})
        print(u2)
        return HttpResponse('用户列表')

注意

request.version
request.versioning_scheme
request.versioning_scheme.reverse(viewname='uuu', request=request)
reverse(viewname='uuu', kwargs={'version': 2})

1.3 注意

在需要获取请求的版本号时,可以通过request.version来获取版本号。

默认版本功能未开启,request.version 返回None。

开启版本支持功能,需要在配置文件中设置DEFAULT_VERSIONING_CLASS

'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',  # 版本信息

其他可选配置:

  • DEFAULT_VERSION 默认版本号,默认值为None
  • ALLOWED_VERSIONS 允许请求的版本号,默认值为None
  • VERSION_PARAM 识别版本号参数的名称,默认值为'version'

1.4 更多支持的版本处理方式

1) AcceptHeaderVersioning

请求头中传递的Accept携带version版本信息

GET /bookings/ HTTP/1.1
Host: example.com
Accept: application/json; version=1.0

2)URLPathVersioning(推荐使用)

URL路径中携带版本信息

urlpatterns = [
    url( r'^(?P<version>(v1|v2))/bookings/$', bookings_list,name='bookings-list' ),
    url( r'^(?P<version>(v1|v2))/bookings/(?P<pk>[0-9]+)/$',bookings_detail,name='bookings-detail')
]

3)NamespaceVersioning

命名空间中定义

# bookings/urls.py
urlpatterns = [
    url(r'^$', bookings_list, name='bookings-list'),
    url(r'^(?P<pk>[0-9]+)/$', bookings_detail, name='bookings-detail')
]

# urls.py
urlpatterns = [
    url(r'^v1/bookings/', include('bookings.urls', namespace='v1')),
    url(r'^v2/bookings/', include('bookings.urls', namespace='v2'))
]

4)HostNameVersioning

主机域名携带 版本信息

GET /bookings/ HTTP/1.1
Host: v1.example.com
Accept: application/json

5)QueryParameterVersioning

查询字符串携带 版本信息

GET /something/?version=0.1 HTTP/1.1
Host: example.com
Accept: application/json

示例

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.QueryParameterVersioning'
}
class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')

class BookInfoSerializer2(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = BookInfo
        fields = ('id', 'btitle', 'bpub_date')

class BookDetailView(RetrieveAPIView):
    queryset = BookInfo.objects.all()

    def get_serializer_class(self):
        if self.request.version == '1.0':
            return BookInfoSerializer
        else:
            return BookInfoSerializer2

# 127.0.0.1:8000/books/2/
# 127.0.0.1:8000/books/2/?version=1.0

1.5 源码流程

# 1.APIView下的dispatch方法
    def dispatch(self, request, *args, **kwargs):
# 2. 进入认证self.initial(request, *args, **kwargs)
    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)
# 进入 self.determine_version(request, *args, **kwargs)
    def determine_version(self, request, *args, **kwargs):