当前位置:首页>python>Python学习之路 - 金庸武侠版 第三重:《独孤九剑》(绝学篇 - 7)

Python学习之路 - 金庸武侠版 第三重:《独孤九剑》(绝学篇 - 7)

  • 2026-10-07 15:50:47
Python学习之路 - 金庸武侠版 第三重:《独孤九剑》(绝学篇 - 7)

喜欢你就关注我

绝世武功:独孤九剑(无招胜有招,适合Web开发,变化多端)
独孤九剑·破箭式
PART 01.
RootK1tana
Django DRF中的序列化器

01

序列化器概述

序列化器是 DRF 处理数据的核心,其主要职责是:

  1. 定义 数据结构 和 验证规则

  2. 实现 模型 与 API数据格式 的转换

  3. 处理 关联关系 和 复杂业务逻辑的验证

02

字段类型

  • BooleanField()

    布尔类型,通常用于表示:真假数据

  • NullBooleanField()

    用于表示:布尔类型的数据,可以是True、False、Null

  • CharField()

    字符串类型,通常用于表示:文本数据

    常用属性:

    max_length(字符串)

    min_length(字符串)

    trim_whitespace

  • EmailField()

    电子邮件类型,通常用于表示:邮箱地址

  • RegexField()

    用于表示正则表达式类型的数据,可以自动验证输入的字符串

  • URLField()

    URL类型,通常用于表示:URL地址

  • UUIDField()

    用于表示:UUID类型的数据,可以自动验证输入字符串

  • IPAddressField()

    用于表示:IP地址类型的数据,可以自动验证输入字符串

  • IntegerField()

    整数类型,通常用于表示:数字数据

    常用属性:

    max_value(数值)

    min_value(数值)

  • FloatField()

    浮点数类型,通常用于表示:小数数据

  • DecimalField()

    高精度十进制数类型,通常用于表示:货币数据

    常用属性:

    max_digits

    decimal_places

  • DateTimeField()

    日期时间类型,通常用于表示:时间戳类型数据

    常用属性:

    format(格式化字符串,如 "%Y-%m-%d")

  • DataField()

    日期类型,通常用于表示:日期数据

  • TimeField()

    时间类型,通常用于表示:时间类型

  • ChoiceField()

    单选择类型,可以定义一个选择列表,用于表示一个固定的选项

  • MultipleChoiceField()

    多选择类型,可以定义多个选择列表,用于表示多个固定的选项

  • FileField()

    文件类型,通常用于表示:文件数据

    常用属性:

    max_size(文件大小限制)

  • ImageField()

    图片类型,通常用于表示:图片数据

  • ListField()

    列表类型,可以用于表示:一个列表数据

  • DictField()

    字典类型,可以用于表示:一个字典数据

  • PrimaryKeyRelatedField()

    关联对象的主键(外键 / 多对多默认)

    queryset(反序列化时必填), many=True,write_only=True,source='tags'

  • SlugRelatedField()

    关联对象的 slug 字段(如用户名)

    常用属性:

    slug_field(指定字段,如 'username')

03

选项参数

  • read_only

    用于 指定字段是否【只能用于序列化】,通常用于表示:只读数据

  • write_only

    用于 指定字段是否【只能用于反序列化】,通常用于表示:敏感数据

  • required

    表明 该字段在【反序列化】时,必须输入(默认True)

  • default

    序列化 和 反序列化时,使用的默认值

  • error_messages

    包含错误编号与错误信息的字典

  • label

    用于HTML展示API页面时,显示的字段名称

  • allow_blank

    设置字段是否允许为 空字符串

  • validators

    设置字段的 验证器

04

Serializer

  • 定义:

    基础序列化器(Serializer)

    适用于非模型数据或需要高度自定义字段的场景

    from rest_framework import serializers# 定义序列化器class UserSerializer(serializers.Serializer):# read_only=True:仅用于序列化(不接受反序列化输入)    id = serializers.IntegerField(read_only=True)    username = serializers.CharField(max_length=100, required=True) # 必传,最大长度100    email = serializers.EmailField(required=False) # 可选,邮箱格式验证    age = serializers.IntegerField(min_value=0, max_value=150) # 数值范围限制
    # 序列化:将Python字典/对象转为JSON格式data = {"username": "testuser","email": "test@example.com","age": 25}serializer = UserSerializer(data=data)if serializer.is_valid(): # 验证数据    print(serializer.validated_data) # 验证通过的字典:{'username': 'testuser', ...}# 可基于validated_data创建模型实例等操作else:    print(serializer.errors) # 验证失败的错误信息
    # 反序列化(从模型实例生成序列化数据)from myapp.models import Useruser = User.objects.get(id=1)serializer = UserSerializer(user)print(serializer.data) # 序列化后的数据:{'id': 1, 'username': 'testuser', ...}

    模型序列化器(ModelSerializer,推荐)

    与 Django 模型绑定,自动根据模型字段生成序列化器字段,简化代码。 适用于大多数与模型相关的 API 场景。

    from rest_framework import serializersfrom myapp.models import Articleclass ArticleSerializer(serializers.ModelSerializer):# 自动关联模型字段,也可自定义额外字段或覆盖默认字段# 例如:添加一个自定义字段(非模型字段) 从关联模型提取字段    author_name = serializers.CharField(source='author.username', read_only=True)class Meta:        model = Article # 绑定的模型        fields = [ # 需要序列化/反序列化的字段'id', 'title', 'content', 'created_time','author', 'author_name'        ]# 或用 exclude 排除不需要的字段:exclude = ['is_deleted']        read_only_fields = ['id', 'created_time'] # 指定只读字段(序列化时返回,反序列化时忽略)        write_only_fields = ['password'] # 指定只写字段(序列化时忽略,反序列化时返回)        extra_kwargs = {# 对字段添加额外约束(覆盖模型默认配置)'title': {'max_length': 200, 'required': True},'content': {'required': False}        }

    * 上述参数:【source】:指定字段数据的来源,可关联模型的属性或方法(如 source='author.username' 表示从关联的 author 模型的 username 字段取值)

    功能:

    数据验证:序列化器的验证逻辑分为

    - 字段级验证

    - 对象级验证

    - 自定义验证器

    (确保数据合法后才进行后续处理)

    (1)字段级验证(单个字段验证)

    通过在序列化器中定义 validate_<field_name> 方法,对特定字段进行验证

    # 验证 title 字段:不能包含敏感词def validate_title(self, value):if'敏感词'in value:raise serializers.ValidationError("标题包含敏感词")return value # 验证通过返回处理后的值

    (2)对象级验证(多字段关联验证)

    通过 validate 方法对多个字段组合进行验证(如 “结束时间必须晚于开始时间”)

    def validate(self, data):# data 是所有字段验证通过后的字典if data['end_time'] <= data['start_time']:raise serializers.ValidationError("结束时间必须晚于开始时间")return data

    (3)自定义验证器(可复用的验证逻辑)

    通过 validators 参数为字段指定自定义验证函数,适合复用的验证规则

    class ProductValidators:# 定义一个验证器:检查字符串是否包含数字def contains_number(value):if not any(char.isdigit() for char in value):            raise serializers.ValidationError("内容必须包含至少一个数字")
    # 在序列化器类中,使用自定义校验器类from .validators import (    ProductValidators,)class ProductSerializer(serializers.Serializer):    name = serializers.CharField(validators=[ProductValidators.contains_number]) # 应用验证器

关联字段处理

当模型包含:外键(ForeignKey)、多对多(ManyToManyField)等关联关系时,序列化器需要特殊处理关联字段

(1)外键关联(ForeignKey)

    简单显示:默认显示关联对象的 id

    嵌套显示:通过嵌套序列化器显示关联对象的详细信息(需注意避免递归嵌套)

(2)多对多关联(ManyToManyField)

    多对多字段默认显示关联对象的 id 列表,

    也可通过 ManyToManySerializer 嵌套显示详情

保存数据(创建与更新)

序列化器验证通过后,可通过 save() 方法创建或更新模型实例

(需在序列化器中实现 create 或 update 方法,ModelSerializer 会自动生成)

(1)ModelSerializer 自动处理

ModelSerializer 已内置create和update方法,直接调用save()即可:

# 创建新对象serializer = ArticleSerializer(data=request.data)if serializer.is_valid():    article = serializer.save() # 调用create方法,返回新创建的模型实例# 更新已有对象article = Article.objects.get(id=1)serializer = ArticleSerializer(article, data=request.data)if serializer.is_valid():    updated_article = serializer.save() # 调用update方法,返回更新后的实例

(2)自定义 create 和 update(Serializer 或复杂场景)

当使用基础 Serializer 或需要自定义保存逻辑时,需手动实现:

class ArticleSerializer(serializers.Serializer):    title = serializers.CharField(max_length=200)    content = serializers.TextField()def create(self, validated_data):# 自定义创建逻辑(如添加默认作者)return Article.objects.create(            author=self.context['request'].user, # 从上下文获取当前用户            **validated_data        )def update(self, instance, validated_data):# 自定义更新逻辑        instance.title = validated_data.get('title', instance.title)        instance.content = validated_data.get('content', instance.content)        instance.save()return instance

* 上述参数:【context】序列化器的上下文(如请求对象 request),可在视图中通过 serializer = ArticleSerializer(context={'request': request}) 传递

使用:

【序列化】操作

  • 序列化 单个对象

    模型类

    class User(models.Model):    name = models.CharField(max_length=5, unique=True, verbose_name='姓名')    age = models.IntegerField(default=0, verbose_name='年龄')class Meta:        db_table = 'tb_users'        verbose_name = '用户'        verbose_name_plural = verbose_name

    序列化器类

    class UserSerializer(serializers.Serializer):    name = serializers.CharField(label='姓名', max_length=6)    age = serializers.IntegerField(label='年龄')

    视图类(many=False)

    class MyView(APIView):def get():# 查询单个用户        user = User.objects.get(id=1)# 使用序列化器对象        serializer = UserSerializer(instance=user, many=False)# 获取序列化后的数据        data = serializer.data
  • 序列化 多个对象

    模型类

    class User(models.Model):    name = models.CharField(max_length=5, unique=True, verbose_name='姓名')    age = models.IntegerField(default=0, verbose_name='年龄')class Meta:        db_table = 'tb_users'        verbose_name = '用户'        verbose_name_plural = verbose_name

    序列化器类

    class UserSerializer(serializers.Serializer):    name = serializers.CharField(label='姓名', max_length=6)    age = serializers.IntegerField(label='年龄')

    视图类(many=True)

    class MyView(APIView):def get():# 查询所有用户        users = User.objects.all()# 使用序列化器对象        serializer = UserSerializer(instance=users, many=True)# 获取序列化后的数据        data = serializer.data
  • 序列化 关联对象

    在 Django 中,模型之间经常存在关联关系(一对一、一对多、多对多);当需要将这些模型序列化为 JSON 或其他格式时,DRF 提供了3种处理关联对象的方式

    PrimaryKeyRelatedField(主键关联字段)

    作用:将关联对象序列化为它们的主键值

    特点:1.简单直接,只显示关联对象的主键

            2.需要指定 read_only=True或queryset参数

            3.many=True表示一对多或多对多关系

    场景:只需要关联对象的 ID;前端可以通过这些 ID 再发起请求获取详细信息

    示例:

    模型定义

    from django.db import modelsclass Author(models.Model):    name = models.CharField(max_length=100)    email = models.EmailField()def __str__(self):return self.nameclass Book(models.Model):    title = models.CharField(max_length=200)    published_date = models.DateField()    author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)def __str__(self):return self.title

    序列化器定义

    from rest_framework import serializersfrom .models import Author, Bookclass AuthorSerializer(serializers.ModelSerializer):    books = serializers.PrimaryKeyRelatedField(many=True, read_only=True)class Meta:        model = Author        fields = ['id', 'name', 'email', 'books']class BookSerializer(serializers.ModelSerializer):class Meta:        model = Book        fields = ['id', 'title', 'published_date', 'author']

    视图定义

    from rest_framework import genericsfrom .models import Author, Bookfrom .serializers import AuthorSerializer, BookSerializerclass AuthorListCreateView(generics.ListCreateAPIView):    queryset = Author.objects.all()    serializer_class = AuthorSerializerclass BookListCreateView(generics.ListCreateAPIView):    queryset = Book.objects.all()    serializer_class = BookSerializer

    输出结果

    {"id": 1,"name": "J.K. Rowling","email": "jk@example.com","books": [1, 2, 3]}

    使用关联对象的序列化器(嵌套序列化)

    作用:将关联对象完全序列化,包含所有字段

    特点:1.显示关联对象的完整信息

            2.需要定义关联对象的序列化器

            3.可能导致数据嵌套层级较深

    场景:需要一次性获取所有关联对象的详细信息;关联对象的数据量不大

    示例:

    模型定义

    from django.db import modelsclass Author(models.Model):    name = models.CharField(max_length=100)    email = models.EmailField()def __str__(self):return self.nameclass Book(models.Model):    title = models.CharField(max_length=200)    published_date = models.DateField()    author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)def __str__(self):return self.title

    序列化器定义

    from rest_framework import serializersfrom .models import Author, Bookclass BookSerializer(serializers.ModelSerializer):class Meta:        model = Book        fields = ['id', 'title', 'published_date']class AuthorSerializer(serializers.ModelSerializer):    books = BookSerializer(many=True, read_only=True)class Meta:        model = Author        fields = ['id', 'name', 'email', 'books']

    视图定义

    from rest_framework import genericsfrom .models import Author, Bookfrom .serializers import AuthorSerializer, BookSerializerclass AuthorListCreateView(generics.ListCreateAPIView):    queryset = Author.objects.all()    serializer_class = AuthorSerializerclass BookListCreateView(generics.ListCreateAPIView):    queryset = Book.objects.all()    serializer_class = BookSerializer

    输出结果

    {"id": 1,"name": "J.K. Rowling","email": "jk@example.com","books": [        {"id": 1,"title": "Harry Potter 1","published_date": "1997-06-26"        },        {"id": 2,"title": "Harry Potter 2","published_date": "1998-07-02"        }    ]}

    StringRelatedField(字符串关联字段)

    作用:将关联对象序列化为它们的 str方法的返回值

    特点:1.依赖模型的 str方法

            2.只读字段(不能用于反序列化)

            3.显示格式有模型定义决定

    场景:只需要显示关联对象的简单字符串表示;不需要完整的对象信息

    示例:

    模型定义

    from django.db import modelsclass Department(models.Model):    name = models.CharField(max_length=100)    location = models.CharField(max_length=100)def __str__(self):returnf"{self.name} ({self.location})"class Employee(models.Model):    name = models.CharField(max_length=100)    position = models.CharField(max_length=100)    department = models.ForeignKey(Department, related_name='employees', on_delete=models.CASCADE)def __str__(self):returnf"{self.name} - {self.position}"

    序列化器定义

    from rest_framework import serializersfrom .models import Department, Employeeclass DepartmentSerializer(serializers.ModelSerializer):    employees = serializers.StringRelatedField(many=True)class Meta:        model = Department        fields = ['id', 'name', 'location', 'employees']class EmployeeSerializer(serializers.ModelSerializer):class Meta:        model = Employee        fields = ['id', 'name', 'position', 'department']

    视图定义

    from rest_framework import genericsfrom .models import Department, Employeefrom .serializers import DepartmentSerializer, EmployeeSerializerclass DepartmentListCreateView(generics.ListCreateAPIView):    queryset = Department.objects.all()    serializer_class = DepartmentSerializerclass EmployeeListCreateView(generics.ListCreateAPIView):    queryset = Employee.objects.all()    serializer_class = EmployeeSerializer

    输出结果

    {"id": 1,"name": "Engineering","location": "Floor 5","employees": ["John Doe - Software Engineer","Jane Smith - Senior Developer"    ]}

【反序列化】操作

  • 数据校验

    数据校验可以调用【is_valid()】方法,会根据对应序列化类 字段的类型 以及一些 选项参数,对【data】中的数据进行校验

     (调用 is_valid 进行数据校验时,除了一些基本的默认验证行为之外,还有以下几种方法) 

    【is_valid()】

    !注意:前端传过来的Json数据(data=request.data),必须要做校验!

    class BookView(APIView):def post(self, request):        serializer = BookSerializers(data=request.data)# is_valid() 校验函数(校验 序列化器类中的 所有字段)# 将 校验成功 的字段,放到:【serializer.validated_data】中# 将 校验失败 的字段,放到:【serializer.errors】中# # !只要有 一个字段校验失败,is_valid()就返回: Falseif serializer.is_valid():          serializer.save() # 序列化器save方法return Response(serializer.data) # 针对self.instance属性做序列化else:# 返回错误信息return Response(serializer.errors)

    【validators】

    针对 指定序列化器字段,添加【validators】选项参数,进行 补充校验 (在 序列化器类 外部定义)

    # 自定义 验证器def age_validators(value):if value < 18:raise serializers.ValidationError('未成年用户禁止操作!')class UserSerializer(serializers.Serializer):    name = serializers.CharField(label='姓名', max_length=6)    age = serializers.IntegerField(label='年龄', validators=[age_validators])

    【validate_<字段名>】

    在序列化器类中,定义特定方法【validate_<字段名>】针对 特定字段 进行补充校验 (在 序列化器类 内部定义)

    class UserSerializer(serializers.Serializer):    name = serializers.CharField(label='姓名', max_length=6)    age = serializers.IntegerField(label='年龄')def validate_age(self, value):if value < 18:raise serializers.ValidationError('未成年用户禁止操作!')return value

    【validate】

    在序列化器类中,定义【validate】方法,针对 多个字段 的内容进行 补充校验 (在 序列化器类 内部定义)

    class UserSerializer(serializers.Serializer):    name = serializers.CharField(label='姓名', max_length=6)    age = serializers.IntegerField(label='年龄')def validate(self, attrs):        age = attrs['age'] # 按照 各个序列化字段名 获取值if age < 18:raise serializers.ValidationError('未成年用户禁止操作!')return attrs
  • 数据保存

    在 数据校验 通过后,想基于【validated_data】完成数据对象的创建,可以通过:【序列化器对象.save()】进行数据保存 

    (在 save() 方法内部会调用 - 序列化器类中的 create 或 update 方法)

    创建序列化器对象时,如果没有传递 instance参数,则调用sava()方法时 create() 被调用;否则 update() 被调用

    class BookSerializers(serializers.Serializer):# 序列化 主键    id = serializers.PrimarilyKey()    title = serializers.CharField(max_length=32)    price = serializers.IntegerField()# 可以自定义 序列化器类中的 字段名,使用 source参数 指定:原字段名    date = serializers.DateField(source="pub_date")def create(self, validated_data):# 如果调用 序列化器save方法,必须重写# create方法 或 update方法# 将数据插入到 数据库中return Book.objects.create(**self.validated_data)def update(self, instance, validated_data):        Book.objects.filter(pk=instance.id).update(**validated_data)        updated_book = Book.objects.get(pk=id)return updated_book
  • ModelSerializer

    概述:基于 模型类 字段,自动生成序列化器类中的字段

    (默认包含了: create() update() 方法的实现)

    使用:

    基本使用

    fields = '__all__'

    class UserSerializer(serializers.ModelSerializer):class Meta:        model = User # 指明 序列化器对应的 模型类        fields = '__all__'# 包含 模型类中的 所有字段

    指定字段

    fields = ('id', 'name')

    class UserSerializer(serializers.ModelSerializer):class Meta:        model = User         fields = ('id', 'name') # 指定字段

    排除字段

    exclude = ('name',)

    class UserSerializer(serializers.ModelSerializer):class Meta:        model = User         exclude = ('name',) # 排除 name字段

    只读字段

    read_only_fields = ('id', 'name')

    class UserSerializer(serializers.ModelSerializer):class Meta:        model = User        fields = ('id', 'name', 'age')        read_only_fields = ('id', 'name') # 只读字段

    仅用于 序列化的字段

    只写字段

    write_only_fields = ('age',)

    class UserSerializer(serializers.ModelSerializer):class Meta:        model = User        fields = ('id', 'name', 'age')        write_only_fields = ('age',) # 只写字段

    仅用于 反序列化的字段

    添加额外参数

    extra_kwargs = { }

    classUserSerializer(serializers.ModelSerializer):classMeta:        model = User        fields = ('id', 'name', 'age')        extra_kwargs = {'name': {'max_length': 3, 'required': True, 'allow_blank': True},'age': {'min_value': 18, 'required': True, 'allow_blank': True}        }

                    篇幅太长,下期再见!

最新文章

随机文章