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格式等

  • 相关阅读:
    所谓的产品哲学
    功能测试
    2019做自己想做的事,学没学过的知识,比如学着去做产品
    Java学习笔记记录(二)
    idea软件破解汉化
    Java学习笔记记录(一)
    Jenkins+VS项目持续集成
    项目研发工作计划开展规划
    Action 操作
    selenium IDE & Remote Control & Webdriver
  • 原文地址:https://www.cnblogs.com/gcxblogs/p/13264218.html
Copyright © 2011-2022 走看看