【三】DRF序列化进阶

devtools/2024/10/19 2:20:45/

【 一 】request对象

request是被drf封装了一层新的request对象,django原生的request 封装在新对象的_request属性里,可以使用request._request访问原生requestdjango为了方便 封装时通过__getattribute____getattr__做了处理 直接使用request.method也能访问到request._request.method

1.解析器

不用的话 默认支持JSONParser,FormParser,MultiPartParser三种解析器

需要改默认 需要改全局配置 setting里新增

例:DEFAULT_PARSER_CLASSES":[“rest_framework.parsers.JSONParser”]

单个配置解析器JSONParser,FormParser
from rest_framework.parsers import JSONParser, FormParser
from rest_framework.negotiation import DefaultContentNegotiationclass UserInFo(APIView):def get(self,request, *args,**kwargs):# 所有解析器parser_classes = [JSONParser,FormParser] #JSON格式和formdata# 根据请求,匹配对应的解析器  寻找content_negotiation_class = DefaultContentNegotiation#获取参数方法request.query_params.get("id") #获取get url参数 id#post请求#request.data
文件解析器
from rest_framework.parsers import MultiPartParser
class UserInFo(APIView):def post(self,request,params):parser_classes = [ MultiPartParser] #文件解析器包括 文件和其他表单#获取文件对象file=request.data.get("img")

2.获取参数

1.读取请求头的content-type类型读取

2.根据不同类型获取解析器

#http://127.0.0.1:8000/getUserInfo/?id=1&&name=xxxx
request.query_params.get("id") #获取get url参数 idrequest.data #获取请求体 post 参数

【 二 】DRF 中的模型序列化(重要)

image-20240413151737446

【0】为什么要使用序列化

'''1 基于APIView写5个接口-做序列化的时候,方法很笨,手动做的-后期如果想多序列化某个或少序列化某个字段,比较麻烦'''#2 借助于 drf 提供的序列化类1 帮助我们快速序列化2 帮助我们做反序列化之前的数据校验3 帮助我们做反序列化# 3 序列化类使用之序列化3.1 写一个类,继承Serialier3.2 在类中写字段,字段就是要序列化的字段3.3 在视图函数中,序列化类,实例化得到对象,传入该传的参数- 多条- 单条3.4 调用序列化类对象的 serializer.data 方法完成序列化

【1】序列化组件使用原理

  1. 序列化: 序列化器会把模型对象转换成字典,经过response以后变成json字符串
  2. 反序列化: 把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
  3. 反序列化: 完成数据校验功能

【2】序列化组件serializer的简单使用

写一个序列化类

在类中写要序列化的字段,想序列化哪个字段,就在类中写哪个字段

在视图类中导入该序列化类,实例化序列化类得到序列化类的对象,将需要序列化的对象传入

序列化类的对象.data 是一个字典

把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse

【3】序列化之查询、删除指定id的接口

# 1 基于View+JsonResponse编写5个接口-1 序列化需要自己做-2 post提交数据,如果是json格式,在request.POST取不到数据--》request.bodydic=json.loads(request.body) # request.body  bytes格式Book.objects.create(**dic)
  • 创建任意名称的py文件,在该文件中创建序列化类,该序列化类需要继承APIView from。
问:

这个序列化创建的表跟我models.py文件中的Book的表并是不是同一张表

答:

在 Django 中,models.py中定义的模型类和rest_framework 中的序列化器不是同一个概念。

在使用 Django REST Framework 进行 API 开发时,通常需要同时使用模型类和序列化器

  1. 模型类(Model):模型类定义了数据的结构,它们对应于数据库中的表。通过定义模型类,您可以轻松地与数据库进行交互,包括检索、创建、更新和删除数据。
  2. 序列化器(Serializer):序列化器用于定义 API 的输入和输出格式。它们负责将模型类实例转换为 JSON 或其他格式,以便通过 API 进行传输,并且还能够将传入的数据反序列化为模型实例。序列化器还可以用于验证传入的数据是否符合预期的格式和规则。

​ 通过使用序列化器,您可以轻松地在 Django 中创建强大的 RESTful API,而无需手动编写数据转换和验证逻辑。序列化器可以帮助您更高效地处理数据,并提供了一种清晰的方式来定义 API 的输入和输出格式。

【3.0】JsonResponse跟Response的区别

JsonResponseResponse 是用于在 Django 中返回 HTTP 响应的两种不同方式。

  1. JsonResponse

    • JsonResponse 是 Django 中的一个类,用于返回 JSON 数据格式的 HTTP 响应。
    • 它是从 django.http 模块中导入的,通常用于 Django 视图函数中。
    • 使用 JsonResponse 可以方便地将 Python 数据结构(如字典或列表)转换为 JSON 格式,并将其作为响应的主体返回给客户端。

示例:

from django.http import JsonResponsedef my_view(request):data = {'key': 'value'}return JsonResponse(data)
  1. Response

    • Response 是 Django REST Framework(DRF)中的一个类,用于返回 HTTP 响应。
    • 它是从 rest_framework.response 模块中导入的,用于 DRF 的视图函数或视图类中。
    • Response 不仅可以返回 JSON 格式的数据,还可以返回其他格式的数据(如 XML、HTML 等)。
    • 它提供了更多的灵活性和功能,如内容协商(Content Negotiation)、状态码的自定义、序列化器的使用等。

示例:

from rest_framework.response import Response
from rest_framework.views import APIViewclass MyAPIView(APIView):def get(self, request):data = {'key': 'value'}return Response(data)

​ 总的来说,JsonResponse 适用于基于 Django 的项目,特别是在处理简单的 JSON 数据时;而 Response 适用于使用 Django REST Framework 构建的 API,提供了更多的功能和灵活性。

【3.1】定义一个Serializer序列化器

from django.db import modelsclass Book(models.Model):name = models.CharField(max_length=88)price = models.IntegerField()publish = models.CharField(max_length=66)
问:

是不是在views.py中使用-序列化后就不需要用from django.http import JsonResponse这个的方法来而是用from rest_framework.response import Response这个方法对吧

答:

​ 在 Django REST Framework 中,通常使用 Response 类来返回 API 的响应,而不是直接使用 Django 中的 JsonResponseResponse 类提供了更多的功能,可以自动将数据序列化为 JSON(或其他格式),并设置正确的 HTTP 头部。这使得处理 API 响应更加简单和灵活。

【3.2】在views.py

  • 在序列化数据的时候,需要指定many=True,因为查到的数据是多条
  • 不需要定义serializer.py文件
def get(self, request):books = Book.objects.all()book_ser = BookSerializer(books, many=True)return Response(book_ser.data)
from .models import Book
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer# 查询多条数据
# http://127.0.0.1:8000/Api01/books/
class BookView(APIView):def get(self, request):res_list = Book.objects.all()# 要序列化的qs对象,但是如果是多条数据,必须加 many=Trueserializer = BookSerializer(instance=res_list, many=True)  # instance=None, data=emptyreturn Response({'code': 100, 'msg': '查询成功', 'results': serializer.data})# 查询单条数据
# http://127.0.0.1:8000/Api01/books/1/
class BookDetailView(APIView):def get(self, request,pk):res_list = Book.objects.filter(pk=pk).first()# 要序列化的qs对象,但是如果是多条数据,必须加 many=True 则单条不用serializer = BookSerializer(res_list)return Response({'code': 100, 'msg': '查询成功', 'results': serializer.data})

image-20240412215058507

image-20240412215709344

  • 删除跟查询一样
from .models import Book
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
from rest_framework import status
from django.shortcuts import get_object_or_404
class BookView(APIView):def delete(self,request,pk):# try:#     # 尝试获取要删除的书籍对象#     book = Book.objects.get(pk=pk)# except Book.DoesNotExist:#     # 如果找不到对应的书籍,则返回 404 错误#     raise NotFound("Book not found")instace = get_object_or_404(Book,pk=pk)instace.delete()return  Response({'code': 100, 'msg': '查询成功'}, status=status.HTTP_204_NO_CONTENT)

image-20240412232908223

注意:

​ 我在上述的代码中,BookView 类继承自 Django Rest Framework 的 APIView 类,用于处理书籍的查询请求。在 get 方法中,您使用 Book.objects.all() 查询了所有的书籍记录,并将其序列化为 JSON 格式的数据,然后将其作为响应返回给客户端。

​ 对于添加、更新和删除操作,您需要更复杂的逻辑来确保数据的合法性和完整性。一般来说,这些操作需要在视图中进行验证,并根据验证结果执行相应的操作。在 Django Rest Framework 中,您可以通过重写视图的 postputpatchdelete 方法来实现这些操作。

【4】反序列化之更改、增加数据

  • 增、改

  • 这个就用到了from rest_framework.exceptions import ValidationError跟函数的validated_data的方法了。

  • 在我们定义的Serializers.py文件中

  • 需要在序列化类中定义校验规则,如果客户端返回给后端的数据符合校验规则,就需要将数据保存到数据库,当数据通过校验的时候,如果不在序列化类中重写update方法就会抛出异常。

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from Api01.models import Bookclass BookSerializer(serializers.Serializer):name = serializers.CharField()price = serializers.IntegerField()publish = serializers.CharField()def create(self,validated_data):# 简单的来说就是验证book里面的数据是否合法book = Book.objects.create(**validated_data)return bookdef update(self, instance, validated_data):# instance:对象# validated_data 数据# 笨办法-y优化--》使用反射instance.name = validated_data.get('name')instance.price = validated_data.get('price')instance.publish = validated_data.get('publish')instance.save()  # 更改保存到数据中return instance
  • urls.py
from django.urls import path,include
# BookView、BookDetailView 这个就是我在views.py 定义的类
from Api01.views import BookView,BookDetailView  
urlpatterns = [path('books/', BookView.as_view()),path('books/<int:pk>/', BookView.as_view()),]
  • views.py

class BookView(APIView):def post(self, request):# 前端无论以什么编码格式--》提交到后端你的数据,都会被解析到 request.data 中,是个字典# 如果是urlencoded或form-data编码--》不能直接这样写,要写成如下# 提取请求数据data = request.dataprint(data)# <QueryDict: {'name': ['啊啥的'], 'price': ['222'], 'publish': ['啊啥的']}># 使用序列化器验证数据obj = BookSerializer(data=data)print(obj)if obj.is_valid():# 如果数据有效,创建新的书籍对象obj.save()return Response({'code': 200,'mes':'添加成功'})else:return Response({'code': 200,'mes':'添加失败!!!','errors':obj.errors})
  • 同理在BookDetailView也是一样的代码

class BookDetailView(APIView):def post(self, request):# 前端无论以什么编码格式--》提交到后端你的数据,都会被解析到 request.data 中,是个字典# 如果是urlencoded或form-data编码--》不能直接这样写,要写成如下# 提取请求数据data = request.dataprint(data)# 使用序列化器验证数据obj = BookSerializer(data=data)print(obj)if obj.is_valid():# 如果数据有效,创建新的书籍对象obj.save()return Response({'code': 200,'mes':'添加成功'})else:return Response({'code': 200,'mes':'添加失败!!!','errors':obj.errors})

image-20240412225806651

class BookDetailView(APIView):def put(self,request,pk):# 提取请求数据data = request.dataprint(data)book = Book.objects.filter(pk=pk).first()res_data = BookSerializer(instance=book, data=data)# 如果数据有效,保存更新后的书籍对象# serializer.is_valid()print(res_data)if res_data.is_valid():res_data.save()return Response({'code': 100, 'msg': '更改成功!!!'})else:return Response({'code': 200, 'mes': '找不到表中的数据', 'errors': res_data.errors})

image-20240413000123667

image-20240413000140546


http://www.ppmy.cn/devtools/22663.html

相关文章

Python实现视频转音频

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、moviepy实现视频转音频 github地址&#xff1a;GitHub - Zulko/moviepy: Video editing with Python 二、示例代码 ""&…

Python selenium

1.搭建环境 1.安装&#xff1a; pip install msedge-selenium-tools 不要使用pip install selenium&#xff0c;我的电脑上没法运行 2.下载驱动 Microsoft Edge WebDriver |Microsoft Edge 开发人员 edge浏览器点设置---关于即可找到版本号&#xff0c;一定要下载对应版…

【人工智能基础】逻辑回归实验分析

实验环境&#xff1a;anaconda、jutpyter Notebook 实验使用的库&#xff1a;numpy、matplotlib 一、逻辑回归 逻辑回归是一个常用于二分类的分类模型。本质是&#xff1a;假设数据服从这个分布&#xff0c;然后使用极大似然估计做参数的估计。 二、实验准备 引入库、预设值…

rknn 麒麟系统调试环境搭建

目录 设置ip 设置静态ip adb usb调试驱动下载 可以用ssh进行远程链接 设置ip 一&#xff0e;解决方法 设置自动获取IP 第一步&#xff1a;编辑文件 sudo vim /etc/network/interfaces 第二步&#xff1a;重启network sudo /etc/init.d/networking restart 设置静态ip au…

31 OpenCV 距离变换和分水岭算法

文章目录 距离变换分水岭算法distanceTransform 距离变换watershed 分水岭算法示例 距离变换 分水岭算法 distanceTransform 距离变换 void cv::distanceTransform (InputArray src,OutputArray dst,int distanceType,int maskSize,int dstType CV_32F) src:输入图像&#xf…

水稻病害检测(YOLO数据集,多分类,稻瘟病、纹枯病、褐斑病、枯心病、霜霉病、水稻细菌性条纹斑病、稻苞虫)

是自己利用LabelImg工具进行手工标注&#xff0c;数据集制作不易&#xff0c;请尊重版权&#xff08;稻瘟病、纹枯病、褐斑病、枯心病、霜霉病、水稻细菌性条纹斑病、稻苞虫&#xff09; 如果需要yolv8检测模型和数据集放在一起的压缩包&#xff0c;可以关注&#xff1a;最新最…

虚假新闻检测——Exploring the Role of Large Language Models in Fake News Detection

Bad Actor, Good Advisor: Exploring the Role of Large Language Models in Fake News Detection 论文地址: Bad Actor, Good Advisor: Exploring the Role of Large Language Models in Fake News Detection| Proceedings of the AAAI Conference on Artificial Intellige…

保证接口幂等性的多种实现方式(数据库方案)

1. 幂等性的概念 接口幂等性是指在软件工程和Web服务领域中&#xff0c;一个接口&#xff08;通常是HTTP API&#xff09;无论被调用一次还是多次&#xff0c;其对系统产生的副作用应该是相同的&#xff0c;即结果保持一致&#xff0c;不会因为多次请求而有所不同。换句话说&am…