django-rest-framework-源码解析001-整体框架 简介 安装 DRF模块 DRF源码入口

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'))
]

django-rest-framework-源码解析001-整体框架
简介
安装
DRF模块
DRF源码入口

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

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