一.请求 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 时, 返回的是一个页面
- 如果使用 Postman 这样的软件访问, 那么展示的就是 JSON 格式, ajax 请求也是 JSON格式
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 下去找