DRF对象与响应

DRF对象与响应

一、请求Request

REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。

1.对象路径

from rest_framework.request import Request

分析源码:

from rest_framework.request import Request


class Request:
    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        # 二次封装request,将原生request作为drf中request对象的 _request 属性
        self._request = request

    def __getattr__(self, item):
        return getattr(self._request, item)
    
    # 请求对象: request.data  前端以三种编码方式传入的数据,都可以取出来
    # 请求对象: request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。

2.常用属性

  • request.data:返回解析之后的请求体数据,类似于Django中标准的request.POSTrequest.FILES属性,但提供如下特性:

    data 特征

    • 包含了解析之后的文件和非文件数据
    • 包含了对POSTPUTPATCH请求方式解析后的数据
    • 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
  • request..query_params:与Django标准的request.GET相同,只是更换了更正确的名称而已。

3.配置能够解析的请求编码格式 : parser_classes

全局配置

  • settings.py文件中配置如下:
REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    ]
}

只能够解析三种请求编码格式:JSONFormDateurlencoded

局部配置

  • 在单独某个视图类中配置:
parser_classes = [FormParser]

配置该项, 视图类首先是先查找自己类中是否有该配置

二、响应Response

1.对象路径

from rest_framework.response import Response

源码分析

from rest_framework.response import Response


class Response:
    def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
        """
        :param data:    你要返回的数据,字典
        :param status:  返回的状态码,默认是200,
            from rest_framework import status  # 在这个路径下, 它把所有使用到的状态码都定义成了常量
        :param template_name: 渲染的模板名字(自定制模板),不需要了解
        :param headers:  响应头,可以往响应头放东西,就是一个字典
        :param content_type:  响应的编码格式,application/json 和 text/html
        """

2.常用属性

  • data:为响应准备的序列化处理后的数据(字典)
  • headers : 用于存放响应头信息的字典
  • status : 状态码, 默认200 (http请求的状态码)
  • template_name : 模板名称, 如果使用HTMLRenderer 时需指明
  • content_type : 响应数据的Content-Type, 通常此参数无需传递, REST framework会根据前端所需类型数据来设置该参数

三、配置响应格式

1.两种显示格式

  • 我们使用浏览器访问 DRF 时, 返回的是一个页面

image-20210416210018964

  • 如果使用 Postman 这样的软件访问, 那么展示的就是 JSON 格式, ajax 请求也是 JSON格式

image-20210416210520119

2.配置响应格式 : renderer_classes

配置的加载执行顺序

  • 先从自己类中找——》项目的setting中找——》默认配置文件中找

全局配置

  • 在settings.py文件中进行配置
# 在 settings.py 文件中进行配置
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
        'rest_framework.renderers.JSONRenderer',  # json渲染器
         'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
    )
}

局部配置

  • 在某个视图类中进行配置
# 在某个视图类中进行配置
from rest_framework.renderers import JSONRenderer
renderer_classes=[JSONRenderer,]

四、状态码

为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量

导入status模块

from rest_framework import status
# "status." 点可取状态码
# 默认响应状态码 : 200

1xx:信息告知

HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS

2xx:成功

HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS

3xx:重定向

HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT

4xx:客户端错误

HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS

5xx:服务端错误

HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED

五、封装自己的Response对象

1.无自定义,手动创建

  • views.py
class Test1(APIView):
    def get(self,request):
        response = {'status':200,'msg':None}
        # 写一堆逻辑,下面伪代码
        res = 1
        if res:
            response['msg'] = '成功'
            response['data'] = {'name':'shawn','age':99}
        else:
            response['status'] = 201
            response['msg'] = '失败'
        return Response(response)
  • urls.py
path('test1/', views.Test1.as_view()),

2.自定义Response类(初始版)

  • myresponse.py文件(自行创建)
class MyResponse():
    def __init__(self):
        self.status = 200
        self.msg = None

    @property
    def get_dict(self):
        return self.__dict__
  • views.py
from mydrf.myresponse import MyResponse

class Test2(APIView):
    def get(self,request):
        # 先实例化得到响应对象
        response = MyResponse()
        # 写一堆逻辑,下面伪代码
        res = 1
        if not res:
            # 直接以的.点方式设置属性
            response.status = 201
            response.msg = '失败了'
        # 返回响应字典
        response.msg = '成功了'
        return Response(response.get_dict)
  • urls.py
path('test2/', views.Test2.as_view()),

3.自定义Response类(高级版)

  • myresponse.py 文件
from rest_framework.response import Response

class APIResponse(Response):
    # 继承 Response 类,并将其内的参数全部拿过来,然后添加自定义的参数(属性)
    # 设置一个kwargs接收其余关键字参数
    def __init__(self, code=200, msg=None, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None, **kwargs):
        dic = {'static': code, 'msg': msg}
        if data:
            dic['data'] = data  # 将data数据放在"data"键中
        if kwargs:
            dic.update(kwargs)  # 将kwargs接收的位置参数更新入dic中
        # 调用父类的__init__方法进行初始化
        super().__init__(data=dic, status=status,
                         template_name=template_name, headers=headers,
                         exception=exception, content_type=content_type)
  • view.py
from mydrf.myresponse import APIResponse

class Test3(APIView):
    def get(self, request):
        # 写一堆逻辑,下面伪代码
        res = 1
        if res:
            return APIResponse(msg='成功!', data={'name': 'shawn'}, next='/index/')
        return APIResponse(status=201, msg='失败', next='/login/')
  • urls.py
path('test3/', views.Test3.as_view()),

版权声明:本文为weixin_44621343原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。