【Django学习】(十一)APIView_请求与响应_GenericAPIView

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 【Django学习】(十一)APIView_请求与响应_GenericAPIView
  • 继承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)

说明:

  1. 在上面代码中,代用父类的get_object()方法,不用再传递pk值,因为get_object()内部已经实现了处理查询集,lookup_field提取出所需要得pk值
  2. 在调用序列化器类传递data时,使用request.data获取到入参数据(继承APIView中的解析器)
  3. 在ProjectViews类方法中(get\post),往往不要直接使用queryset类属性,去获取查询集对象
  1. 一般需要使用self.get_queryset(),去获取查询集对象,因为更加灵活,后续可以重写父类的get_queryset()
  2. 调用self.get_serializer,获取序列化器类对象,原因同理

相关文章
|
1月前
|
IDE 关系型数据库 MySQL
Django学习一:创建Django框架,介绍Django的项目结构和开发逻辑。创建应用,编写主包和应用中的helloworld
这篇文章是关于如何创建一个Django框架,介绍Django的项目结构和开发逻辑,并指导如何创建应用和编写“Hello, World!”程序的教程。
38 3
Django学习一:创建Django框架,介绍Django的项目结构和开发逻辑。创建应用,编写主包和应用中的helloworld
|
1月前
|
SQL Java 数据库
Django学习三:views业务层中通过models对实体对象进行的增、删、改、查操作。
这篇文章是关于如何使用Django框架的ORM系统在视图(views)层面进行数据库的增、删、改、查操作的教程。
18 0
Django学习三:views业务层中通过models对实体对象进行的增、删、改、查操作。
|
1月前
|
关系型数据库 MySQL Java
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
这篇文章是关于如何使用Django框架配置MySQL数据库,创建模型实例,并自动或手动创建数据库表,以及对这些表进行操作的详细教程。
61 0
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
|
5月前
|
编解码 前端开发 JavaScript
技术经验分享:Django学习日记
技术经验分享:Django学习日记
|
3月前
|
存储 前端开发 Serverless
中后台前端开发问题之Django项目中接收和处理用户的抽奖请求如何解决
中后台前端开发问题之Django项目中接收和处理用户的抽奖请求如何解决
19 0
|
6月前
|
前端开发 数据库 Python
使用 Python 的 Web 框架(如 Django 或 Flask)来建立后端接口,用于处理用户的请求,从数据库中查找答案并返回给前端界面
【1月更文挑战第13天】使用 Python 的 Web 框架(如 Django 或 Flask)来建立后端接口,用于处理用户的请求,从数据库中查找答案并返回给前端界面
244 7
|
5月前
|
前端开发 数据管理 API
Django REST framework中GenericAPIView与混入扩展类详解
Django REST framework中GenericAPIView与混入扩展类详解
|
5月前
|
前端开发 Python
Django框架中Ajax GET与POST请求的实战应用
Django框架中Ajax GET与POST请求的实战应用
|
5月前
|
JSON 缓存 前端开发
Django视图层探索:GET/POST请求处理、参数传递与响应方式详解
Django视图层探索:GET/POST请求处理、参数传递与响应方式详解
|
5月前
|
前端开发 JavaScript 安全
跨域问题与Django解决方案:深入解析跨域原理、请求处理与CSRF防护
跨域问题与Django解决方案:深入解析跨域原理、请求处理与CSRF防护