- 继承DRF中APIView之后,那么当前视图就具备了认证、授权、限流等功能
- 继承DRF中APIView之后,每一个实例方法中的request为Request对象
- Request类拓展了Django中的HttpRequest类,具备很多额外优秀的功能
- Request类与HttpRequest类中的所有功能兼容
- 查询字符串参数:request.GET、request.query_param推荐
- 获取json格式参数:request.body(还需要decode解码)、request.data(直接获取到字典)
- 获取www-form参数:request.POST、request.data
- 获取multipart/form-data:request.body、request.POST、request.data
一、APIView
1、Request_解析类
from rest_framework.views import APIView
视图集中引用APIView
class ProjectsDetailViews(APIView): . . . class ProjectsViews(APIView): # 创建数据 def post(self, request): ret = { "msg": "传参异常", "code": 404 } # json_str = request.body.decode('utf-8') # try: # data_dict = json.loads(json_str) # 如果入参不是json格式数据,抛出异常 # except json.JSONDecodeError: # return JsonResponse(ret, json_dumps_params={"ensure_ascii": False}, status=404) # 反序列化输入 # serializer_obj = ProjectModelSerializer(data=data_dict) serializer_obj = ProjectModelSerializer(data=request.data) if not serializer_obj.is_valid(raise_exception=True): ret.update(serializer_obj.errors) return JsonResponse(ret, json_dumps_params={"ensure_ascii": False}, status=404) serializer_obj.save() return JsonResponse(serializer_obj.data, json_dumps_params={"ensure_ascii": False}, status=200)
- 上面的代码中注释掉入参为json格式数据的处理,使用drf框架中自带的解析类
JSONParser:解析JSON请求内容。
FormParser:解析 HTML 表单内容
MultiPartParser:解析多部分HTML表单内容,支持文件上传
设置解析器:
可以使用
DEFAULT_PARSER_CLASSES
设置全局默认的解析器集。例如,以下设置将仅允许具有JSON
内容的请求,而不是JSON或表单数据的默认值。
- 定义解析器类,用于解析不通的前端参数类型
- 会自动根据请求头中Content-Type来解析参数
- 无论前端传递这三种参数中的哪一种参数,都可以使用request.data去获取
本项目中的配置文件添加配置:
发起post请求:
如果发起的数据请求格式在解析类中没有定义,则发起请求时返回提示请求格式不支持
# 创建数据 def post(self, request): ret = { "msg": "传参异常", "code": 404 } # json_str = request.body.decode('utf-8') # try: # data_dict = json.loads(json_str) # 如果入参不是json格式数据,抛出异常 # except json.JSONDecodeError: # return JsonResponse(ret, json_dumps_params={"ensure_ascii": False}, status=404) # 反序列化输入 # serializer_obj = ProjectModelSerializer(data=data_dict) serializer_obj = ProjectModelSerializer(data=request.data) if not serializer_obj.is_valid(raise_exception=True): ret.update(serializer_obj.errors) return JsonResponse(ret, json_dumps_params={"ensure_ascii": False}, status=404) serializer_obj.save() return JsonResponse(serializer_obj.data, json_dumps_params={"ensure_ascii": False}, status=200)
指定了解析类后,我们在视图集里就可以不用再手动处理json格式或者其他格式的入参(代码被注释掉的部分) ,drf内部会自动帮我们处理
2、Response_渲染类
- 定义渲染类,用于返回不同类型的数据
- 会自动根据请求头中Accept进行渲染
- 如果前端不指定Accept,那么默认返回json格式的数据
- 如果指定Accept为application/json,那么也会以json数据返回
- 如果指定Accept为text/html(浏览器发起GET请求会自动指定),那么会以html形式返回
- 在DRF的视图中,一定要以Response返回
- Response类为HttpResponse的子类,具备HttpResponse中的所有功能
- 可以自动根据请求头中的Accept参数,来返回相应数据格式到前端
- 第一个参数为Python中的常用数据类型(字典、嵌套字典的列表),尽量使用序列化器类.data
- status指定响应状态码,content_type指定响应体数据类型
settings.py配置文件
指定了渲染类后,我们在views.py视图集里也可以不用再手动处理json格式的出参了,drf会内部自动帮我们处理并返回,所以可以不使用JsonResponse进行返回了。
# return JsonResponse(serializer_obj.data, json_dumps_params={"ensure_ascii": False}, status=200)
可以使用Response进行返回:
return Response(serializer_obj.data,status=status.HTTP_201_CREATED)
二、GenericAPIView
- GenericAPIView是APIView的子类,具备APIView的所有功能
- 往往需要指定queryset和serializer_class两个类属性
- queryset指定当前类视图需要使用的查询集
- serializer_class指定当前类视图需要使用的序列化器类
import ast import json from django.http import HttpResponse, JsonResponse, Http404 from rest_framework.response import Response from rest_framework import status from django.views import View from rest_framework.views import APIView from rest_framework.generics import GenericAPIView from .models import ProjectsModel from django.db import connection from .serializers import ProjectSerializer, ProjectModelSerializer, ProjectNameSerializer # 能够动态的查询生成的sql语句 connection.queries # Create your views here. # class ProjectsDetailViews(APIView): class ProjectsDetailViews(GenericAPIView): queryset = ProjectsModel.objects.all() serializer_class = ProjectModelSerializer def get(self, request, pk): pro = self.get_object() serializer_obj = self.serializer_class(instance=pro) return Response(serializer_obj.data, status=status.HTTP_200_OK) # 更新数据 def put(self, request, pk): # 查出对应id的数据 query_data = self.get_object() serializer_obj = self.serializer_class(instance=query_data, data=request.data) serializer_obj.is_valid() # 保存更新的数据 serializer_obj.save() return Response(serializer_obj.data, status=status.HTTP_201_CREATED) # 删除数据 def delete(self, request, pk): ret = { "msg": "删除成功!" } # 根据id查出对应数据 query_data = self.get_object() # 删除指定数据 query_data.delete() # 一般删除数据的输出为None return Response(ret,status=status.HTTP_204_NO_CONTENT) # class ProjectsViews(APIView): class ProjectsViews(GenericAPIView): queryset = ProjectsModel.objects.all() serializer_class = ProjectNameSerializer # 查询全部数据 def get(self, request): # 往往不要直接使用queryset类属性,去获取查询集对象 # 一般需要使用self.get_queryset(),去获取查询集对象,因为更加灵活,后续可以重写父类的get_queryset() pro_data = self.get_queryset() serializer_obj = self.get_serializer(instance=pro_data, many=True) return Response(serializer_obj.data, status=status.HTTP_200_OK) # 创建数据 def post(self, request): serializer_obj = self.get_serializer(data=request.data) serializer_obj.is_valid(raise_exception=True) serializer_obj.save() return Response(serializer_obj.data, status=status.HTTP_201_CREATED)
说明:
- 在上面代码中,代用父类的get_object()方法,不用再传递pk值,因为get_object()内部已经实现了处理查询集,lookup_field提取出所需要得pk值
- 在调用序列化器类传递data时,使用request.data获取到入参数据(继承APIView中的解析器)
- 在ProjectViews类方法中(get\post),往往不要直接使用queryset类属性,去获取查询集对象
- 一般需要使用self.get_queryset(),去获取查询集对象,因为更加灵活,后续可以重写父类的get_queryset()
- 调用self.get_serializer,获取序列化器类对象,原因同理