• 版本控制


    准备

    新建一个项目,采用路由分发的方式,采用之前的数据库表的例子并添加修改

    目录结构如下:

    demo
    	api
            migrations
                __init__.py
            __init__.py
            admin.py
            apps.py
            models.py
            tests.py
            urls.py			# 路由分发后的urls
            views.py
        demo
        	__init__.py
        	settings.py
        	urls.py
        	wsgi.py
        templates
        db.sqlite3
        manage.py
    
    # demoapimodels.py
    
    from django.db import models
    
    class UserGroup(models.Model):
        title = models.CharField(max_length=32)
    
    class UerInfo(models.Model):
        user_type_choices = (
            (1, '普通用户'),
            (2, 'VIP'),
            (3, 'SVIP'),
        )
        user_type = models.IntegerField(choices=user_type_choices)
        username = models.CharField(max_length=32, unique=True)
        password = models.CharField(max_length=64)
    
        roles = models.ManyToManyField("Role")
        group = models.ForeignKey("UserGroup")
    
    class UserToken(models.Model):
        user = models.OneToOneField(to='UerInfo')
        token = models.CharField(max_length=64)
    
    class Role(models.Model):
        title = models.CharField(max_length=32)
    
    # demodemourls.py
    
    from django.conf.urls import url, include
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^api/', admin.site.urls),
        url(r'^api/', include('api.urls')),
    ]
    
    # demoapiurls.py
    
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        url(r'^users/$', views.UsersView.as_view()),
    ]
    
    # demoapiviews.py
    
    from django.shortcuts import render, HttpResponse
    from rest_framework.views import APIView
    
    class UsersView(APIView):
    
        def get(self, request, *args, **kwargs):
            # 通过原生的request
            version = request._request.GET.get('version')
            print(version)
            return HttpResponse("用户列表")
    

    启动项目,在浏览器输入 http://127.0.0.1:8000/api/users/?version=v1 ,后台会返回一个 v1,这是通过访问原生的 request 去获取版本

    还有一种方法,通过 query_params 访问

    # demoapiviews.py
    
    from django.shortcuts import render, HttpResponse
    from rest_framework.views import APIView
    
    class UsersView(APIView):
    
        def get(self, request, *args, **kwargs):
            version = request.query_params.get('version')
            print(version)
            return HttpResponse("用户列表")
    

    因为这是 query_params 内部自己访问原生的 request ,达到同样的效果

    自定义版本组件

    URL中通过GET传参

    通过上面的 query_params ,可以自定义一个版本的组件,从而获取版本

    # demoapiviews.py
    
    from django.shortcuts import render, HttpResponse
    from rest_framework.views import APIView
    
    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):
            print(request.version)
            return HttpResponse("用户列表")
        
    

    启动项目,在浏览器输入 http://127.0.0.1:8000/api/users/?version=v2 ,后台会返回一个 v2

    还可以使用内置的方法去获取版本

    # demoapiviews.py
    
    from django.shortcuts import render, HttpResponse
    from rest_framework.views import APIView
    from rest_framework.versioning import QueryParameterVersioning
    
    class UsersView(APIView):
    
        versioning_class = QueryParameterVersioning
    
        def get(self, request, *args, **kwargs):
            print(request.version)
            return HttpResponse("用户列表")
    
    
    # 进入 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)
            # is_allowed_version是允许的版本
            if not self.is_allowed_version(version):
                raise exceptions.NotFound(self.invalid_version_message)
            return version
    	
        # 反向生成URL
        def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
            url = super(QueryParameterVersioning, self).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
    
    

    可以在配置文件中设置默认的版本

    # demodemosettings.py
    
    # 在末尾添加
    REST_FRAMEWORK = {
        "DEFAULT_VERSION": 'v1',	# 默认版本
        "ALLOWED_VERSION": ['v1', 'v2'],	# 允许使用的版本
        "VERSION_PARAM": 'version'	# url中的key值
    }
    
    

    现在在浏览器中,只能通过访问 http://127.0.0.1:8000/api/users/http://127.0.0.1:8000/api/users/?version=v1http://127.0.0.1:8000/api/users/?version=v2 的方式从后台获取数据

    URL路径中传参(推荐使用)

    它也是个内置的方法

    # demoapiviews.py
    
    from django.shortcuts import render, HttpResponse
    from rest_framework.views import APIView
    from rest_framework.versioning import URLPathVersioning
    
    class UsersView(APIView):
    
        versioning_class = URLPathVersioning
    
        def get(self, request, *args, **kwargs):
            print(request.version)
            return HttpResponse("用户列表")
    
    
    

    因为是通过路径传参,所以在 url 中需要有所改动

    # demoapiurls.py
    
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view()),
    ]
    
    
    

    这时在浏览器中通过 http://127.0.0.1:8000/api/v1/users/ 也可以在后台获取 v1,这时推荐的使用方式

    可以设置在配置文件中,做全局的设置,在视图函数中便可以省略

    # demodemosettings.py
    
    REST_FRAMEWORK = {
        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
        "DEFAULT_VERSION": 'v1',
        "ALLOWED_VERSION": ['v1', 'v2'],
        "VERSION_PARAM": 'version'
    }
    
    
    # demoapiviews.py
    
    from django.shortcuts import render, HttpResponse
    from rest_framework.views import APIView
    
    class UsersView(APIView):
        def get(self, request, *args, **kwargs):
            print(request.version)
            return HttpResponse("用户列表")
    
    

    源码流程

    请求进来,先走 dispatch ,对 request 进行封装,走 initial

    def initial(self, request, *args, **kwargs):
    	
        ... # 省略的内容
        
        # 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)
    
    
    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)
        # 处理版本类的对象,就是 settings.py中 URLPathVersioning类的对象
        scheme = self.versioning_class()
        # 返回两个值,第一个是调用determine_version的方法,根据请求获取版本
        # 第二个scheme是处理版本的对象
        return (scheme.determine_version(request, *args, **kwargs), scheme)
    
    
    class APIView(View):
        ... # 省略的内容
        versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
    
    

    先处理版本再走认证、权限、频率

    反向生成URL

    from django.shortcuts import render, HttpResponse
    from rest_framework.views import APIView
    from django.urls import reverse
    
    class UsersView(APIView):
    
        def get(self, request, *args, **kwargs):
    
            # 1. 获取版本
            print(request.version)
            # 2. 获取版本处理的对象
            print(request.versioning_scheme)
    		
            # 反向自动生成URL(你在浏览器访问的url会给你打印出来)
            u1 = request.versioning_scheme.reverse(viewname='uu', request=request)
            print(u1)
            
            # 手动生成
            u2 = reverse(viewname='uu', kwargs={'version':2})
            print(u2)
    
            return HttpResponse("用户列表")
    
    
    

    总结

    使用

    配置文件

    REST_FRAMEWORK = {
        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
        "DEFAULT_VERSION":'v1',
        "ALLOWED_VERSIONS":['v1','v2'],
        "VERSION_PARAM":'version',
    }
    
    

    路由系统

    urlpatterns = [
        url(r'^api/', admin.site.urls),
        url(r'^api/', include('api.urls')),
    ]
    
    urlpatterns = [
        url(r'^(?P<version>[v1|v2]+)/users/$', views.UsersView.as_view(), name='uu'),
    ]
    
    

    视图

    • 获取版本
    • 获取版本处理的对象
    • 反向生成URL
  • 相关阅读:
    从无到有制作Deb包的一个实例
    Redis内存存储结构分析
    岳麓实践论
    金砖四国(巴西、俄罗斯、印度和中国)
    用LLVM开发新语言
    QQ云输入法
    http://baike.baidu.com/view/1926473.htm
    21世纪商业评论
    update ubuntu to 11.10
    gnu make 中文手册教程pdf
  • 原文地址:https://www.cnblogs.com/qiuxirufeng/p/10458791.html
Copyright © 2020-2023  润新知