drf 请求与响应

一.请求 Request

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

0.对象路径

from rest_framework.request import Request

1.常用属性

  • request.data : 存放的是原来 request.body 中的所有数据, (前端传过来的三种格式的数据)
# data 特征
- 包含了解析之后的文件和非文件数据
- 包含了对POST、PUT、PATCH请求方式解析后的数据
- 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
  • request.query_params : 与Django标准的request.GET相同,只是更换了更正确的名称而已, 也可以直接使用 request.GET

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

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

只能解析这三种请求编码格式 : urlencoded, formdata, json

  • 局部配置
# 在某个视图类中配置
parser_classes = [FormParser]

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

二.响应 Response

0.对象路径

from rest_framework.response import Response

1.常用属性

  • 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

  • 全局配置
# 在 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,]
  • 配置查找顺序
配置的加载执行顺序: 先从自己类中找 -> 项目的setting中找 -> 默认配置文件中找

四.状态码

为了方便设置状态码,REST framewrok自己提供了许多常用状态码, 并将其都做成了常量

0.导入 status 模块

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

1.1xx : 信息告知

HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS

2.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

3.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

4.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

5.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()),

六.补充

Django 中的 templates 文件夹下的模板文件, 在查询的时候优先会到项目的 templates 文件夹下去找, 找不到再去相应的 APP 下去找, 找不打就报错, 不会跑到其他的 APP 下去找


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