zoukankan      html  css  js  c++  java
  • django-rest-framework-源码解析001-整体框架

    简介

    Django Rest Framework是一个强大且灵活的工具包,主要用以构建RESTful风格的Web API。

    Django REST Framework(简称DRF)可以在Django的基础上迅速实现API,并且自身还带有 基于WEB的测试和浏览页面,可以方便的测试自己的API。DRF几乎是Django生态中进行前后端 分离开发的默认库。

    Django REST Framework具有以下功能和特性:

    • 自带基于Web的可浏览的API,对于开发者非常有帮助
    • 支持OAuth1a 和OAuth2认证策略
    • 支持ORM或非ORM数据源的序列化
    • 高可自定制性,多种视图类型可选
    • 自动生成符合 RESTful 规范的 API 支持
    • OPTION、HEAD、POST、GET、PATCH、PUT、DELETE等HTTP方法
    • 根据 Content-Type 来动态的返回数据类型(如HTML、json)
    • 细粒度的权限管理(可到对象级别)
    • 丰富的文档和强大的社区支持
    • Mozilla、Red Hat、 Heroku和Eventbrite等知名公司正在使用

    安装

    在项目环境中直接pip安装

    pip install djangorestframework

    安装完毕,在项目配置文件中,注册app:

    INSTALLED_APPS = (
    ...
    'rest_framework',
    )

    如果你想使用基于浏览器的可视化的API目录,并且希望获得一个登录登出功能,那么可以在根 路由下添加下面的路由('api-auth/' 可以随意指定),这个功能类似Django自带的admin后台:

    urlpatterns = [
    ...
    path('api-auth/', include('rest_framework.urls'))
    ]

    为了登录操作,也许你还要生成数据表,创建超级用户。

    python manage.py makemigrations
    python manage.py migrate
    python manage.py createsuperuser

    DRF模块

    DRF有几大功能模块: 

      1. 序列化模块(Serializer): (rest_framework.serializers) 对数据进行序列化和反序列化, 序列化即通过django的model对象创建序列化对象, 进而将对应的字段转换为json格式, 反序列化即通过请求中的json数据创建反序列化对象, 进而将json数据转化为字典格式, 序列化模块中提供了常用的三种序列化类:

        1.1 Serializer类(rest_framework.serializers.Serializer): 基础的序列化类, 需要自己编写所有的字段以及create和update方法,比较底层,抽象度较低

        1.2 ModelSerializer类(rest_framework.serializers.ModelSerializer): 更常用的序列化类, 不需要手动编写所有字段, 会根据指向的model自动生成默认的字段和简单的create和update方法

        1.3 ListSerializer类(rest_framework.serializers.ListSerializer): 当使用ModelSerializer进行群改(一次更新多个model对象)时, 需要用到ListSerializer并重写update()方法

      2. 请求模块(Request): (rest_framework.request.Request) 对django的原生request对象进行二次封装, 将原生request对象封装至DRF自己的Request的_request属性中, 并新增了解析器, 认证器等属性

      3. 解析模块(Parses) : (rest_framework.parser) 对request中携带的常见Content-Type进行相应的解析:

        3.1 JSONParser类(rest_framework.parser.JSONParser): 解析Content-Type为 application/json 的数据

        3.2 FormParser类(rest_framework.parser.FormParser): 解析Content-Type为 application/x-www-form-urlencoded 的数据(普通form表单提交的数据)

        3.3 MultiPartParser类(rest_framework.parser.MultiPartParser): 解析Content-Type为 multipart/form-data 的数据(比普通form表单支持的类型更多)

        3.4 FileUploadParser类(rest_framework.parser.FileUploadParser): 解析Content-Type为 */* 的数据, 一般为文件类型的数据

      4. 认证模块(Authentication): (rest_framework.authentication) 对request进行验证, 判断请求的用户是否合法, 一般将用户分成三类: 游客(不携带认证信息的匿名用户), 非法用户(携带了认证信息的用户但信息是错误的), 合法用户(携带了正确的认证信息)

      5. 权限模块(Permission): (rest_framework.permission) 对通过认证的用户判断其是否有权限访问该页面

      6. 频率模块(Throttle): (rest_framework.throttling) 限制同一个访问客户端的IP或用户等指标每秒访问服务器的次数

      7. 响应模块(Response): (rest_framework.response) 将序列化后的数据以及其他常见response数据如http状态码/headers等封装成Response对象

      8. 异常模块(Exception): (rest_framework.exceptions) 捕获认证模块/权限模块/频率模块/自定义视图类/响应模块中所抛出的异常, 并将异常信息转化为json返回给前端

      9. 渲染模块(Renders): (rest_framework.renderers) 返回json数据还是将数据渲染为HTML页面等

    DRF源码入口

    rest_framework.views.as_view()

    使用DRF时, 需要将视图文件(view.py)定义的类(CBV)继承rest_framework的APIView(APIView是django原生View的子类)或者将定义的函数(FBV)用rest_framework的api_view装饰器进行装饰. 因此在url中调用的view.as_view()方法或者api_view中调用的as_view方法就是rest_framework.views.as_view()方法, 即rest_framework重写了django原生的view中的as_view()方法

        @classmethod
        def as_view(cls, **initkwargs):
            """
            Store the original class on the view function.
    
            This allows us to discover information about the view when we do URL
            reverse lookups.  Used for breadcrumb generation.
            """
            代码省略......# 1.调用父类View的as_view
            view = super().as_view(**initkwargs)
            view.cls = cls
            view.initkwargs = initkwargs
            
            # 2.跳过csrf认证
            # Note: session based authentication is explicitly CSRF validated,
            # all other authentication is CSRF exempt.
            return csrf_exempt(view)

    分析as_view()方法, 发现其主要做了两件事: 1. 调用父类View的as_view  2. 跳过csrf认证

    因此主要的逻辑还是在父类View的as_view中, 来到父类View.as_view的代码, 发现其定义了一个view方法, 最后返回这个view方法, 在view方法中实例化了一个cls的对象(self), 然后返回了self.dispatch方法的返回值

        @classonlymethod
        def as_view(cls, **initkwargs):
            """Main entry point for a request-response process."""
         代码省略......
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                if hasattr(self, 'get') and not hasattr(self, 'head'):
                    self.head = self.get
                self.setup(request, *args, **kwargs)
                if not hasattr(self, 'request'):
                    raise AttributeError(
                        "%s instance has no 'request' attribute. Did you override "
                        "setup() and forget to call super()?" % cls.__name__
                    )
                return self.dispatch(request, *args, **kwargs)
            代码省略......return view

    rest_framework.views.dispatch()

    注意上面的cls就是as_view的cls参数, 也就是外层APIView中的as_view的cls参数, 也就是APIView, 那么这里cls创建的self就是APIView的对象, 那么调用的dispatch方法就是APIView对象的dispatch方法, 如果我们自定义的视图类没有重写dispatch方法, 那么就会走APIView的dispatch方法, 可以看到APIView中确实重写了dispatch方法, 这里就是DRF的核心入口

        def dispatch(self, request, *args, **kwargs):
            """
            `.dispatch()` is pretty much the same as Django's regular dispatch,
            but with extra hooks for startup, finalize, and exception handling.
            """
            self.args = args
            self.kwargs = kwargs
    
            # 请求模块/解析模块
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
            self.headers = self.default_response_headers  # deprecate?
    
            try:
                # 三大认证模块
                self.initial(request, *args, **kwargs)
    
                # 通过反射获取自定义视图类中request.method对应的方法
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self, request.method.lower(),
                                      self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
    
                # 响应模块
                response = handler(request, *args, **kwargs)
    
            except Exception as exc:
                # 异常处理模块
                response = self.handle_exception(exc)
    
            # 渲染模块
            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response

    在这个dispatch中主要分为了5部分

    1.  request = self.initialize_request(request, *args, **kwargs) 这里初始化了一个DRF的Request对象, 除了包括了django原生request, 还包括了解析器, 权限器等

    2.  self.initial(request, *args, **kwargs) 这里是对Request进行三大校验, 包括认证模块(authentication), 权限模块(permission), 频率模块(throttle)

    3.  response = handler(request, *args, **kwargs) 这里是先通过反射机制获取自定义视图类中request.method对应的方法, 然后调用该方法, 得到处理结果

    4.  response = self.handle_exception(exc) 这里是捕获三大校验和获取响应所抛出的异常, 并得到异常的处理结果

    5.  self.response = self.finalize_response(request, response, *args, **kwargs) 这里将上面的到的正常或异常处理结果(response)再进行最终的渲染处理, 可以渲染为单纯的json数据或者是方便浏览器查看的html格式等

  • 相关阅读:
    免费的视频、音频转文本
    Errors are values
    Codebase Refactoring (with help from Go)
    Golang中的坑二
    Cleaner, more elegant, and wrong(msdn blog)
    Cleaner, more elegant, and wrong(翻译)
    Cleaner, more elegant, and harder to recognize(翻译)
    vue控制父子组件渲染顺序
    computed 和 watch 组合使用,监听数据全局数据状态
    webstorm破解方法
  • 原文地址:https://www.cnblogs.com/gcxblogs/p/13264218.html
Copyright © 2011-2022 走看看