序列化与反序列化

作用:

定义序列化器:序列化器必须要直接继承或者间接结成serializers.Serializer,Serializer有个子类ModelSerializer

使用教程

1

序列化的使用:不仅可以转换模型对象的数据格式,python中的对象的属性对应序列化器的字段也可以转换为字典或者列表

序列化器编写:

复制代码
from rest_framework import serializers


class StudentSerializer(serializers.Serializer):
    """学生信息序列化器"""
    # 1.声明请求与响应过程中的字段
    id = serializers.IntegerField()
    name = serializers.CharField()
    age = serializers.IntegerField()
    sex = serializers.BooleanField()
    description = serializers.CharField()
    # 2.序列化器用的是ModelSerializer,则需要声明Meta
    # 3.验证代码
    # 4.编写数据库模型的添加与更新代码
复制代码

视图编写:

复制代码
"""
暂时使用django中的原生views,未使用drf视图类
"""
from FRAMEWORK.models import Student  # 使用Student的模型
from django.shortcuts import render
from sers.serializers import StudentSerializer  # 导入序列化器
from django.views import View
from django.http.response import JsonResponse


class StudentView1(View):
    def get(self, request):
        # 查询单条数据
        """序列化器序列化阶段使用:
        实例化序列化器得到序列化对象
        参数:serializer=StudentSerializer(
        instance=本次转换数据格式的数据 来自数据库 模型类[单个]/查询集[多个]
        date=需要进行数据转换的数据 来自客户端 字典/者列表
        contest={}:从视图中传递给序列化器的第三方数据(比如request) 字典
        many=设置本次转换的数据是否为多条数据(决定了序列化器能否用for进行数据转换,True/False)
        )
        """
        # 查询单条数据
        # serializer = StudentSerializer(instance=student)
        # 查询多条数据
        # serializer = StudentSerializer(instance=student_list,many=True)
        # 更新一条
        # serializer = StudentSerializer(instance=student,date=date)
        # 添加一条数据
        # serializer = StudentSerializer(date=date)
        # 删除一条数据
        # 一般不使用序列化器

        student = Student.objects.first()  # 查询数据
        serializer = StudentSerializer(instance=student)  # 序列化数据
        # 转换后的数据其实是:serializer.data
        return JsonResponse(serializer.data)

    # def get(self, request):
    #     """查询多条数据"""
    #     student_list = Student.objects.all()
    #     serializer = StudentSerializer(instance=student_list, many=True)
    #     # print(serializer.data)#有序字典OrderedDict写入读取时顺序一致
    #     return JsonResponse(serializer.data, safe=False)  # 为了允许序列化非dict对象,将safe参数设置为False
复制代码

反序列化的使用

数据验证:验证后在反序列化保存为模型对象

在反序列化前需要调用 序列化对象的is_valid() 方法进行序列化内部的预设的代码教验,返回True/False,

失败时,可以通过 序列化对象的errors 属性获取错误信息(字典格式),若是非字段错误,通过rest_framework提供的配置:NOT_FIELDS_ERRORS_KEY控制错误字典中的键值

成功后:通过 序列化器对象的validated_data属性获取验证后的数据

复制代码
def get(self, request):
        """反序列化:用户添加或者更新数据时使用"""
        # 模拟用户传来的数据
        data = {
            "name": "小明",
            "age": 17,
            "sex": 1,
            "description": "懒人一枚",
        }
        # 反序列化操作
        serializer = StudentSerializer(data=data)
        # 错误信息两种方式
        # 方式1:
        # raise_exception=True,失败时drf自动抛出异常
        # serializer.is_valid(raise_exception=True)

        ret = serializer.is_valid()
        print(ret)
        if ret:
            # 获取验证后的结果
            print(f"serializer.validated={serializer.validated_data}")
        # 方式2:我们需要捕获错误信息
        else:
            # 获取报错结果
            print(f"serializer.errors={serializer.errors}")
            # 拆分一下报错结果
            for item in serializer.errors.items():
                print(f"错误字段={item[0]}")
                for error in item[1]:
                    print(f"错误处={error.code}")
                    print(f"错误原因={error}")
        return JsonResponse({"msg": "ok"})
复制代码

is_valid()调用了数据声明的验证方法,添加更多验证方法使用下列三种方法

1)validate_字段名

复制代码
# 3.1 单字段补充验证:
    def validate_name(self, data):
        """
        必须以"validate_<字段名>"作为方法名
        必须返回此字段,回传序列化器,否则数据丢失,可以改动,必须返回
        :param data:接收验证字段(名字随意)
        :return:
        """
        print(f"validate_name验证字段:{data}")
        if data == "java":
            # 序列化器抛出异常可以通过
            raise serializers.ValidationError(code="name", detail="当前字段为敏感字眼")
        return data
复制代码

2)validate

复制代码
# 3.2 多字段验证(只能由1个或者0个)
    def validate(self, attrs):
        """
        必须以"validated"作为方法名
        会接收客户端所有字段数数
        必须返回此字段,否则丢失
        :return:
        """
        # 多字段一般用于用户注册时密码与确认密码的2个字段必须一样此类情况(因为request并没有传过来)
        age = attrs.get("age")
        sex = attrs.get("sex")
        if sex != 3 and age <= 18:
            raise serializers.ValidationError("年龄18以下的,性别应该保密")
        return attrs
复制代码
  • 3)validators
  • 复制代码
    # 3.3单字段验证函数
    age = serializers.IntegerField(validators=[Adulted])
    sex = serializers.ChoiceField(choices=SEX_OPTIONS, validators=[NoNum])

    def Adulted(data): if data < 10: raise serializers.ValidationError("年龄低于10不能使用本产品") return data def NoNum(data): if data > 3 or data < 1: raise serializers.ValidationError("sex只能出现指定数字") return data

    复制代码

     

  • 反序列化-保存数据
  • 解释,如果在调用save()方法时没有传入instance(也就是下列添加数据),就会调用序列化器中的create()方法,
  • 传入了instance对象(更新操作)则会调用序列化器中的update()方法
  • 同时针对特殊场景:例如注册与修改时使用同一序列化器,修改不需要填写其他信息,允许部分字段的更新,允许使用partial参数进行部分更新
  • 复制代码
            data = {
                "name": "工三",
                "age": 21,
                "sex": 1,
                "description": "描述2",
                "class_null": "101",
            }
            # 获取本次修改模型对象
            student = Student.objects.get(pk=pk)
            serializer = StudentSerializer(instance=student, data=data,partial=True)
    复制代码

     

  • 第一种:添加数据

 

复制代码
 def get5(self, request):
        """添加数据反序列化时,调用模型保存数据"""
        # 模拟用户传来的数据
        data = {
            "name": "ofa",
            "age": 19,
            "sex": 2,
            "class_null": "23",
            "description": "",
        }
        serializer = StudentSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        # 调用save方法模型存储数据(序列化器内部的save不是django的)
        student = serializer.save()  # 接收Student对象,可操作
        print(serializer.data)
        return JsonResponse({"msg": "保存了吗?"})

#但是.save()方法并不适用,需要在序列化器中重写

# 视图调用序列化器的save时要写create方法,否则报错
def create(self, validated_data):
    """添加数据 到模型中的实现方法
        所有数据都是预先校验过直接添加即可
    """
    # 添加数据完全属于模型
    # student=Student.objects.create(**validated_data)
    # 存在字段不属于模型,指定字段即可
    student = Student.objects.create(
        name=validated_data.get("name"),
        age=validated_data.get("age"),
        sex=validated_data.get("sex"),
        class_null=validated_data.get("class_null")
    )
    # 强烈建议返回添加后的模型对象
    return student
复制代码

 

 

  • 第二种更新数据
  • 复制代码
    def get6(self, request):
            """更新数据反序列化时,调用模型保存数据
                restful中规定:修改删除数据需要pk值,写在url中
            """
            pk = 3
            data = {
                "name": "工三",
                "age": 21,
                "sex": 1,
                "description": "描述2",
                "class_null": "101",
            }
            # 获取本次修改模型对象
            student = Student.objects.get(pk=pk)
            serializer = StudentSerializer(instance=student, data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            print(serializer.data)
            # 再次序列化将更新数据返回客户端
            return JsonResponse({"msg": "更新好了吗?"})
    
    
        def update(self, instance, validated_data):
            """
            :param instance: 本次更新数据库模型
            :param validated_data:客户端提价的已验证的数据
            :return:
            """
            instance.name = validated_data.get("name")
            instance.age = validated_data.get("age")
            instance.sex = validated_data.get("sex")
            instance.class_null = validated_data.get("class_null")
            # 可选字段单独验证一下
            if validated_data.get("description"):
                instance.description = validated_data.get("description")
            # 调用模型的save方法
            instance.save()
            return instance
    复制代码

     

posted @   Hide_凉辰  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示