wtf

rest_framework框架的封装特点

import rest_framework

from rest_framework.views import APIView   #视图
from rest_framework.request import Request   #请求
from rest_framework.response import Response  #响应
from rest_framework.exceptions import APIException  #异常
from rest_framework.pagination import PageNumberPagination  #分页
from rest_framework.settings import APISettings   #配置
from rest_framework.parsers import JSONParser    #解析
from rest_framework.filters import OrderingFilter   #排序

原生django与drf比较:

csrf对APIView的get和post(drf)都没有拒绝,csrf对View的post(原生django)请求会拒绝

APIView的请求生命周期

  • APIView类继承View类,重写了as_view和dispatch方法
  • 重写的as_view方法,主体还是View的as_view,只是在返回视图view函数地址时,局部禁用了csrf认证
  • 重写的dispatch方法:
    • 在执行请求逻辑前:请求模块(二次封装request)、解析模块(三种数据包格式的数据解析)
    • 在执行请求逻辑中:异常模块(执行出现任何异常交给异常模块处理)
    • 在执行请求逻辑后:响应模块(二次封装response)、渲染模块(响应的数据能JSON和页面两种渲染)
      APIView的as_view(局部禁用csrf) => 走父级的as_view调用dispatch分发请求 => APIView自己重写了dispatch,使用自己完成分发 => 分发前完成request二次封装、数据解析 => 三大认证 => 请求的实际响应(自己的视图类的处理分发) => 出现了异常,就会交给异常模块处理异常 => 响应模块完成响应、渲染模块可以json或浏览器两种方式渲染

请求模块

  • 将wsgi的request对象转化成drf的Request类的对象
  • 封装后的request对象完全兼容wsgi的request对象,并且将原request保存在新request._request
  • 重写格式化请求数据存放位置
    • 拼接参数:request.query_params
    • 数据包参数:request.data
request._request 被 request完全兼容
	request.query_params | request.data
  • 源码分析:
    • 入口:APIVIew的dispatch方法的 request=self.initialize_request(request, *args, **kwargs)
    • print(request._request.method) 在内部将wsgi的request赋值给request._request#
    • print(request.method) 就是通过__getattr__走的是request._request.method
    • print(request.query_params) 走的是方法属性,就是给request._request.GET重新命名
    • print(request.data) 走的是方法属性,值依赖于request._full_data

settings中的REST_FRAMEWORK = { },先找自定义的,然后找系统默认设置的

解析模块

只处理数据包参数-->form-data,urlencoded,json

  • 全局配置所有视图类的解析方式,解析配置可以配置三种
  • 局部配置当前视图类的解析方式,解析配置可以配置三种
  • 配置的查找顺序:局部(视图类的类属性)=》全局(settings文件中的drf配置)=》默认(drf的默认配置)
  • 源码分析:
    • 入口:APIVIew的dispatch方法的 request=self.initialize_request(request, *args, **kwargs)
    • 获取解析类:parsers=self.get_parsers(),
    • 进行局部全局默认配置查找顺序进行查找:return [parser() for parser in self.parser_classes]
局部配置:parser_classes = [JSONParser, FormParser, MultiPartParser]
	全局配置:
		'DEFAULT_PARSER_CLASSES': [
            'rest_framework.parsers.JSONParser',
            'rest_framework.parsers.FormParser',
            'rest_framework.parsers.MultiPartParser'
        ],

响应模块

data:响应数据

status:响应的网络状态码(可以自定义状态码对应的信息)

template_name:drf完成前后台不分离返回页面,但是就不可以返回data(禁用)

headers:响应头,一般不规定,走默认

exception:一般异常响应,会将其设置成True,默认false(可以不设置)

content_type:默认就是application/json,不需要处理
r=Response() r.method=request.method

Respose(data=常量|列表|字典, status=网络状态码)

渲染模块

postman请求结果是json,浏览器请求结果是页面

可以全局与局部配置

局部配置:renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
	全局配置:
		'DEFAULT_RENDERER_CLASSES': [
        	'rest_framework.renderers.JSONRenderer',
        	'rest_framework.renderers.BrowsableAPIRenderer',  # 上线后尽量关闭
    	],

异常模块

  • 默认的exception_handler只处理drf客户端异常形成的response对象,服务器异常不做处理,返回None
settings中配置:'EXCEPTION_HANDLER': 'api.exception.exception_handler',
	重写exception_handler方法:
# 一定要在settings文件中将异常模块配置自己的异常处理函数
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response

# 先交给drf处理客户端异常,如果结果response为None代表服务器异常,自己处理
# 最终一定要在日志文件中记录异常现象
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)
    detail = '%s - %s - %s' % (context.get('view'), context.get('request').method, exc)
    if not response:  # 服务端错误
        response =  Response({'detail': detail})
    else:
        response.data = {'detail': detail}

    # 核心:要将response.data.get('detail')信息记录到日志文件
    # logger.waring(response.data.get('detail'))

    return response

Content-Type

该标头告诉客户端实际返回的内容类型

Accept:text/xml;
Content-Type:text/html
即代表希望接受的数据类型是xml格式,本次请求发送的数据的数据格式是html。

  • form表单发送数据编码格式是urlencoded(Content-Type: application/x-www-form-urlencoded),post方式提交数据

  • form 表单发送文件编码格式:form-data(Content-Type: multipart/form-data)

    • 这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 form 的 enctyped 等于这个值。
  • ajax发送json格式数据编码格式:application/json(Content-Type: application/json)

    • 用来告诉服务端消息主体是序列化后的 JSON 字符串
    • django后端针对json格式的数据 不会做任何处理 数据怎么来的 只会原封不动的放到request.body中,需要自己手动处理(序列化JSON.stringify)
posted on 2019-12-24 21:16  wtfss  阅读(301)  评论(0)    收藏  举报