必知必会必须掌握:使用【serializers.Serializer序列化器类+django的View视图类】在views.py视图文件中序列化和反序列化过程的开发模板

# 视图类
from django.views import View

class ProjectTestView(View):
    """
    a.获取所有数据
    b.创建一条数据
    """
    def get(self, request):
        """
        序列化输出到前端的过程规则:
            a.创建模型对象
            b.将上面已创建好的的模型对象传递给序列化器类的instance属性,多个对象必须传递many=True
            c.通过return JsonResponse(使用序列化器对象.data)将序列化之后的数据返回给前端
        """
        projects = Project_t.objects.all()
        serializer = serializerstest.ProjectSerializer(instance=projects, many=True)
        return JsonResponse(serializer.data, safe=False, json_dumps_params={'ensure_ascii':False})

    def post(self, request):
        """
        反序列化输入的过程规则:
        1.将前端传递的数据,转化为字典类型数据
        2.创建序列化器对象,data传递的参数为待校验的字典数据
        3.必须调用序列化器对象.is_valid()方法,对数据进行校验,序列化器对象.validated_data属性为校验通过的数据
        4.进行数据入库操作,模型对象数据创建:模型类.objects.create(**序列化器对象.validated_data)
        5.返回到前端:
            a.将上面已创建好的的模型对象传递给序列化器类的instance属性,多个对象必须传递many=True
            b.通过return JsonResponse(使用序列化器对象.data)将序列化之后的数据返回给前端

        """
        data = {
            'code': 0,
            'msg': ''
        }
        request_dict = json.loads(request.body.decode('utf-8'))
        serializer = serializerstest.ProjectSerializer(data=request_dict)
        if serializer.is_valid(raise_exception=True):
            project_obj = Project_t.objects.create(**serializer.validated_data)
            serial = serializerstest.ProjectSerializer(instance=project_obj)
            return JsonResponse(serial.data, status=200, json_dumps_params={'ensure_ascii': False})
        data['code'] = 1
        data['msg'] = '参数有误'
        return JsonResponse(data, status=400, json_dumps_params={'ensure_ascii': False})

image

🔍 两个Serializer调用的区别

这两个调用虽然使用同一个序列化器类,但功能和参数完全不同:

📋 功能对比表

特性 Serializer(data=request_dict) Serializer(instance=projects)
作用 反序列化(输入验证) 序列化(输出格式化)
参数类型 data 参数(字典) instance 参数(模型对象)
数据流向 客户端 → 服务器 服务器 → 客户端
主要用途 验证传入数据 格式化输出数据
常用方法 .is_valid(), .save() .data

💡 详细解释

1. Serializer(data=request_dict) - 反序列化(输入验证)

作用:验证客户端传入的数据是否合法

# request_dict 是从请求体中解析的字典数据
# 例如:{"name": "我的项目", "desc": "项目描述"}

serializer = serializerstest.ProjectSerializer(data=request_dict)

流程

  1. 接收原始客户端数据
  2. 验证字段类型、长度、必填等规则
  3. 转换为Python原生数据类型(validated_data
  4. 准备用于创建或更新数据库对象

常用方法

if serializer.is_valid(raise_exception=True):
    validated_data = serializer.validated_data  # 获取验证后的数据
    instance = serializer.save()  # 保存到数据库

2. Serializer(instance=projects) - 序列化(输出格式化)

作用:将数据库对象格式化为客户端可接收的数据

# projects 是从数据库获取的模型对象实例
# 例如:<Project_t: id=1, name="我的项目">

seria = serializerstest.ProjectSerializer(instance=projects)

流程

  1. 接收数据库模型实例
  2. 将模型字段转换为JSON可序列化的数据类型
  3. 添加可能的计算字段或格式化数据
  4. 准备返回给客户端的响应数据

常用方法

response_data = seria.data  # 获取序列化后的字典数据
return JsonResponse(response_data)  # 返回给客户端

🎯 参数类型详解

data 参数(反序列化)

  • 类型dict 字典
  • 内容:客户端发送的原始数据
  • 示例
request_dict = {
    "name": "我的项目",
    "desc": "这是一个项目描述",
    "status": "active"
}

instance 参数(序列化)

  • 类型:Django模型实例
  • 内容:从数据库查询得到的对象
  • 示例
projects = Project_t.objects.get(id=1)
# projects 是一个模型实例:<Project_t: id=1, name="我的项目">

🔄 完整数据流程

# 1. 客户端发送JSON数据 → 服务器接收
request_dict = json.loads(request.body.decode('utf-8'))
# request_dict: {"name": "新项目", "desc": "描述"}

# 2. 反序列化验证(data参数)
serializer = serializerstest.ProjectSerializer(data=request_dict)
if serializer.is_valid(raise_exception=True):
    # serializer.validated_data: {"name": "新项目", "desc": "描述"}
    
    # 3. 创建数据库对象
    projects = Project_t.objects.create(**serializer.validated_data)
    # projects: <Project_t: id=2, name="新项目", desc="描述">
    
    # 4. 序列化输出(instance参数)
    seria = serializerstest.ProjectSerializer(instance=projects)
    # seria.data: {"id": 2, "name": "新项目", "desc": "描述"}
    
    # 5. 返回给客户端
    return JsonResponse(seria.data)

🚀 简化写法

你的代码可以简化为使用序列化器的save()方法:

request_dict = json.loads(request.body.decode('utf-8'))
serializer = serializerstest.ProjectSerializer(data=request_dict)

if serializer.is_valid(raise_exception=True):
    # 直接使用save()创建对象,避免手动create
    instance = serializer.save()
    
    # 直接返回序列化数据,无需创建新的序列化器实例
    return JsonResponse(
        serializerstest.ProjectSerializer(instance).data, 
        status=201,  # 201 Created 更合适
        json_dumps_params={'ensure_ascii': False}
    )

✅ 总结

  • Serializer(data=...):用于验证输入,参数是字典
  • Serializer(instance=...):用于格式化输出,参数是模型对象

这两个调用分别处理数据流入和流出的两个方向,确保了数据的完整性和一致性。

# 模型类
from django.db import models
from utils.base_model import BaseModel

class Project_t(BaseModel):
    name = models.CharField(max_length=50, verbose_name="项目名称", help_text="请输入项目名称", unique=True)
    leader = models.CharField(max_length=50, verbose_name="项目负责人", help_text="请输入项目负责人")
    is_execute = models.BooleanField(default=False, verbose_name="是否启动项目", help_text="请选择是否启动项目")
    desc = models.TextField(max_length=125, verbose_name="项目描述", help_text="请输入项目描述", blank=True, null=True)

    class Meta:
        db_table = "tb_project_test"
        verbose_name = "项目test表"
        verbose_name_plural = verbose_name
        ordering = ['id']

    def __str__(self):
        return f'Project: {self.name},id: {self.id}'


# 序列化器类
from rest_framework import serializers, validators
from . import modelstest


def validate_project_name(value):
    if "项目" not in value:
        raise serializers.ValidationError("项目名称需要包含<保密>关键词")


def validate_project_leader(value):
    if "鲁" not in value:
        raise serializers.ValidationError("领导名字中必须包含<鲁>关键词")


# class ProjectSerializer(serializers.ModelSerializer):
class ProjectSerializer(serializers.Serializer):
    """
    为什么需要使用序列化器类serializers?
    1.可以实现序列化输出操作
    2.可以实现反序列化输入操作
    3.数据校验操作
    4.数据库操作
    如何定义序列化器类?
    1.一般在子应用中创建serializers.py文件,用于定义序列化器类
    2.必须继承Serializer类,或者Serializer的子类
    3.序列化输出的参数名要与创建的序列化器字段(序列化器类中的类属性)名称保持一致
    4.序列化输出的参数类型要与创建的序列化器字段(序列化器类中的类属性)类型保持一致
    5.序列化器字段必须为Field子类
    6.序列化器字段类型种类有哪些?
        a.IntegerField -> int
        b.CharField -> str
        c.BooleanField -> bool
        ......
    如何使用序列化器类实现序列化输出操作?
    1.先创建序列化器对象
    2.在创建序列化器对象时,使用instance传递参数
    3.序列化操作的对象有四种?
        a.模型对象  -- 无需传递many关键字参数
        b.普通对象  -- 无需传递many关键字参数
        c.查询集合  -- 必须传递many=True
        d.嵌套普通对象的列表 -- 必须传递many=True
    4.使用创建序列化器对象.data属性获取序列化之后的数据(字典或者嵌套字典的列表)

    定义的序列化器字段以及常用参数?
    1.默认定义的序列化器字段,都会进行序列化输出
    2.定义的序列化器字段名称和类型必须与模型类中的字段名或者普通对象的属性名保持一致
    3.公共的参数
        a.label、help_text 和orm模型类中的verbose_name 、help_text参数一致。都是同样的意思
        b.如果当前字段仅仅是只需要反序列化输入,可以设置write_only=True,表示只写入数据库,不做前端输出
        c.如果当前字段仅仅是只需要序列化输出,可以设置read_only=True, 表示只做前端输出,没有入库的操作
        d.required指定某个字段是否为必传字段,默认required=True,默认定义的字段为必传字段
        e.如果required=False,那么该字段为可选参数,如果前端没有传递,那么序列化输出时不会输出,如果前端有传递,那么序列化输出时会输出
        f.如果同时设置required=False,和write_only=True,那么write_only=True参数会被忽略
        g.如果同时设置required=False,read_only=True, 那么read_only=True参数会被忽略
        h.default给某个字段指定默认值
        i.如果给某个字段设定了默认值,那么前端未传递该字段,会把该字段作为输入值,如果指定了该字段,那么会使用该字段作为输入值
        j.某个字段不同,同时指定default=True,required=True
        k.allow_null指定某个字段是否允许传递null值,如果制定了allow_null=True,那么允许传递null值
        l.error_message可以定制字段的具体错误提示信息,该参数必须传递字典类型,将具体校验规则名称作为key,把报错提示字符串作为value
        m.validators参数指定自定义校验规则(校验器),为列表类型
        n.可以使用drf提供的UniqueValidator对字段是否唯一性进行校验,queryset参数为所有模型对象的查询集,message指定校验失败的错误提示信息
        o.可以在序列化器类外定义校验函数,作为validators参数值列表中的元素(使用校验函数名)
        p.定义校验函数,必须接受一个函数(待校验的值),如果校验不通过,必须得抛出serializers.ValidationError异常,
            可以指定具体的报错字符串作为ValidationError参数,如果校验通过无需返回
        q.某个字段的校验顺序:
            当前字段的类型
            当前字段的所有校验规则进行校验(字段的所有校验关键字参数、validators参数列表中的所有校验规则一般都会被校验)
            单字段校验方法
        r.可以在类里面对单个字段进行校验
            单字段校验的方法名称必须为validate_该字段的名称
            仅仅只有当定义的字段上所有校验规则通过的情况下,才会在类里卖弄调用对单字段进行校验的方法。
    4.CharField类型字段
        a.默认该字段不允许传递空字符串
        b.可以指定allow_blank=True, 那么允许该字段传递空字符串
        c.max_length指定最大长度字节数,min_length指定最小字节长度
        d.如果前端传递该字段值为str,int,float,会自动转化为字符串类型,如果传递其他类型会校验失败
        e.trim_whitespace=True, 默认值为True,会自动清空左右两侧的空格。
    5.IntegerField类型字段
        max_value:参数最大值
        min_value:参数最小值
    6.DateTimeField类型字段
        a.format指定格式化字符串

    如何使用序列化器类实现反序列化输入操作?
    1.在创建序列化器对象时,使用data传递待校验的参数,需要接收json转化为字典之后的数据
    2.传递给data的参数,必须为待校验的字典数据
    3.必须得调用序列化器对象.is_valid()方法,才会开始对数据进行校验
    4.仅仅只有调用is_valid()方法之后,才能通过序列化器对象.errors属性获取校验的结果,一般为字典类型
        仅仅只有调用is_valid()方法之后,才能通过序列化器对象.validated_data属性获取校验通过的数据,一般为字典类型
    5.默认定义的序列化器字段,都会进行反序列化输入,前端都必须得传递,也会进行序列化输出操作
        read_only=False
        write_only=False
    6.往往把前端向后端发起请求的过程称为写入数据库write过程,也称为反序列化输入,只写入数据库,不向前端返回该字段数据
    7.往往把后端向前端响应数据的过程称为读,read过程,也称为序列化输出,只把数据库中该字段的数据,返回给前端
    8.如果当前字段仅仅只需要反序列化输入,可以设置write_only=True
    9.如果当前字段仅仅只需要序列化输出,可以设置read_only=True
    10.可以在调用序列化器对象.is_valid()方法时,指定raise_exception=True,那么校验不通过时,会抛出异常,否则不会抛出异常
    11.如果未调用序列化器对象.is_valid()方法,那么是不会开始校验的,
        所以不饿能调用序列化器对象的.errors属性(获取错误提示字典信息)、data属性(序列化输出的数据)、validated_data属性(获取校验通过的数据)
    read -> 输出
    write -> 输入



    """
    id = serializers.IntegerField(read_only=True, max_value=100000, min_value=1, label='项目id', help_text='输出项目id')
    name = serializers.CharField(max_length=100, required=True, label='项目名称', help_text='项目名称', min_length=2,
                                 validators=[validate_project_name,
                                             validators.UniqueValidator(queryset=modelstest.Project_t.objects.all(),
                                                                        message="项目名称已存在")])
    leader = serializers.CharField(max_length=100, required=True, error_messages={
        'min_length': '长度不能少于1个字符',
        'max_length': '长度不能大于100个字符',
        'null': '项目负责人不能为null',
        'required': '项目负责人为必填参数',
        'blank': '项目负责人不能为空字符串'
    }, allow_blank=True, trim_whitespace=True,
                                   validators=[validate_project_leader,
                                               validators.UniqueValidator(queryset=modelstest.Project_t.objects.all(),
                                                                          message='该负责人已经存在')])
    is_execute = serializers.BooleanField(write_only=True)
    desc = serializers.CharField(max_length=255, required=True, help_text='请输入项目简介:')
    create_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M:%S')
    def validate_name(self, value):
        if not str(value).endswith('33'):
            raise serializers.ValidationError("项目名称必须以33结尾")
        return value

    def validate_desc(self, value):
        if not value:
            raise serializers.ValidationError("需要输入描述,255长度以内")
        return value

posted @ 2025-09-13 16:22  大海一个人听  阅读(11)  评论(0)    收藏  举报