【DRF-07】rest-framework之版本

  • 1.基于url的get传参方式(不推荐)
    • 1.1:通过自定义版本控制类,获取版本
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView

class ParamVersion(object):
    def determine_version(self,request,*args,**kwargs):
        version = request._request.GET.get("version")
        return version

class UserView(APIView):
    versioning_class = ParamVersion
    def get(self,request,*args,**kwargs):
        # version = request._request.GET.get("version")
        # print(version)
        #
        # version1 = request.query_params.get("version")
        # print(version1)

        print(request.version)
        return HttpResponse("用户列表")
  • 1.2:小知识点,我们在通过request获取信息时,先看restframework中有没有,如果没有就取原生request中的方法。实现原理
class Request:
  @property
  def query_params(self):
      """
      More semantically correct name for request.GET.
      """
      return self._request.GET

  def __getattr__(self, attr):
      """
      If an attribute does not exist on this instance, then we also attempt
      to proxy it to the underlying HttpRequest object.
      """
      try:
          _request = self.__getattribute__("_request")
          return getattr(_request, attr)
      except AttributeError:
          return self.__getattribute__(attr)

  • 1.3:restframework已经有内置类帮我们实现了上面的功能
    • 1.3.1:使用
# 全局配置
REST_FRAMEWORK = {
    "DEFAULT_VERSION":"v1",
    "ALLOWED_VERSIONS":["v1","v2"],
    "VERSION_PARAM":"version",
}

# 视图
from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning
class UserView(APIView):
    versioning_class = QueryParameterVersioning
    def get(self,request,*args,**kwargs):

        print(request.version)
        return HttpResponse("用户列表")
- 1.3.2:原理
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)
        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):
        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
  • 2.基于url的正则方式(推荐)
    • 2.1:使用
# urls.py
from django.urls import path,re_path
from api import views
urlpatterns = [
    re_path(r'^(?P<version>[v1|v2]+)/users/$', views.UserView.as_view()),
]

# 视图
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning

class UserView(APIView):
    versioning_class = URLPathVersioning
    def get(self,request,*args,**kwargs):
        print(request.version)
        return HttpResponse("用户列表")
  • 3.源码流程
    • 3.1:还是走dispatch-->>initial
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
  • 3.2: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)
    """
    if self.versioning_class is None:
        return (None, None)
    # 处理版本类的对象,URLPathVersioning对象
    scheme = self.versioning_class()
    return (scheme.determine_version(request, *args, **kwargs), scheme)
  • 3.3:视图中使用
# 取版本
request.version
# 取处理版本的对象
request.versioning_scheme
  • 4.反向生成url
    • 4.1:使用
urlpatterns = [
    re_path(r'^(?P<version>[v1|v2]+)/users/$', views.UserView.as_view(),name='uuu'),
]

# 视图
from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning

class UserView(APIView):
    versioning_class = URLPathVersioning
    def get(self,request,*args,**kwargs):
        print(request.version)

        u1 = request.versioning_scheme.reverse(viewname='uuu',request=request)
        print(u1)
        return HttpResponse("用户列表")

posted @ 2024-05-28 20:36  Tony_xiao  阅读(4)  评论(0编辑  收藏  举报