深入理解 Django REST Framework 的 Serializer(上)

一、什么是 Serializer?------ 概念与作用

1.1、核心定义

Serializer 负责将复杂数据类型(如 Django 模型实例)转换为 Python 原生数据类型(如 dict),以便渲染为 JSON/XML;同时也能将解析后的数据反向验证并转换回复杂类型。

1.2、两大核心功能

  • 序列化(Serialization):对象 → 字典(用于响应)
  • 反序列化(Deserialization):字典 → 对象(用于请求)

而在序列化与反序列化中一定绕不开下表的方法,也是我们理解序列化器的前提

这两个方法均在 rest_framework\serializers.py下的 Serializer 类中,后续我会一一讲解

|----------|----------------------------------|-------------------------|
| 方向 | 方法 | 用途 |
| 输入(反序列化) | to_internal_value() → validate() | 把前端数据转成干净 Python 对象 |
| 输出(序列化) | to_representation() | 把 Python 对象转成 JSON 安全字典 |
[序列化器的两个任务]

二、如何定义 Serializer?

2.1 以serializers.Serializer 为例

1、定义类继承serializers.Serializer

python 复制代码
from rest_framework import serializers


class MobileLoginModelSerializer(serializers.Serializer):

2、根据业务以及逻辑定义字段

在这里我是做短信登录,所以需要用到 mobile code(短信验证码)字段,而手机号长度通常为11位,短信验证码长度在4-6位,设置只写。

++注:如果你不明白为什么要写这些,或者为什么要写这些,可以先跳过。等学完 反序列化 回头再看这里++

python 复制代码
from rest_framework import serializers


class MobileLoginModelSerializer(serializers.Serializer):
    mobile = serializers.CharField(
        max_length=11, write_only=True)
    
    code = serializers.CharField(
        min_length=4, max_length=6, write_only=True)

也许你还知道ModelSerializer 这个序列化器,你可能会疑惑?为什么 ModelSerializer 中不需要写那么多参数,因为这个序列化器会继承其在Model中声明过的字段及其参数。而普通 Serializer 的字段不会自动获得任何约束,除非你写出来!


3、定义字段验证方法及整体验证方法

其中如果是对字段的验证方法 遵循以下原则

  1. 方法名以 validate_xxx命名 xxx为该字段名称 比如要验证手机号 在上述我的字段命名为mobile,所以就是 validate_mobile
  2. 必须返回一个值,如果你只是检验没有修改 直接返回参数中的value即可,如果你对这个参数进行了修改就返回修改后的值

如果是对整体进行验证 遵循以下原则

  1. 必须返回参数的attrs,可以对这个attrs进行添加新数据,但是必须返回!
python 复制代码
from rest_framework import serializers


class MobileLoginModelSerializer(serializers.Serializer):
    
    ...省略上述代码

    def validate_mobile(self, value):
        if not User.objects.get(mobile=value):
            raise serializers.ValidationError("手机号不存在",code='mobile')
        return value

    def validate(self, attrs):
        mobile = attrs.get('mobile')
        code = attrs.get('code')

        redis = get_redis_connection('sms_code')
        key = f'sms_{mobile}_login'

        # 1.获取Redis短信验证码判断是否存在
        stored_code = redis.get(key)
        if stored_code is None:
            raise serializers.ValidationError("验证码已过期",code='code')
        # 2.判断 code:attrs 与 code:redis
        if stored_code.decode() != code:
            raise serializers.ValidationError("验证码错误,请重新确认",code='code')

        redis.delete(key)
        attrs['user'] = User.objects.get(mobile=mobile)
        return attrs

三、如何使用定义好的 Serializer?

3.1 以APIView视图为例

1、实例化序列化器类

我们需要传入的参数分别是

request.data 用于反序列化数据校验

context 在这里先按下不表,后面会出一个专门的文章讲解这个参数的作用。新手只需记住必须传这个参数

python 复制代码
from rest_framework.views import APIView
from .serializers import MobileLoginModelSerializer

class MobileLoginAPIView(APIView):
    def post(self, request):
        # 1. 序列化器验证数据
        serializer = MobileLoginModelSerializer(
                        data=request.data, context={'request':request}
                    )

2、调用is_valid()方法

调用这个方法 序列化器就会校验本次传入的数据是否合法(根据我们设置的校验规则)

python 复制代码
from rest_framework.views import APIView
from .serializers import MobileLoginModelSerializer

class MobileLoginAPIView(APIView):
    def post(self, request):
        # 1. 序列化器验证数据
        serializer = MobileLoginModelSerializer(
                        data=request.data,
                        context={'request':request})

        if not serializer.is_valid():
            return Response(data=serializer.errors,status=status.HTTP_400_BAD_REQUEST)

四、总结

一个简单但完整的序列化器使用过程就是这样的,可以总结成以下的步骤

  1. 定义字段,设置字段参数
  2. 定义字段校验方法,整体校验方法 (如有需求)
  3. 实例化序列化器,调用is_valid方法

在下篇文章中,我会继续深入研究 is_valid方法做了什么 如何完成反序列化及数据校验

相关推荐
小码哥_常3 小时前
Spring Boot 牵手Spring AI,玩转DeepSeek大模型
后端
0xDevNull4 小时前
Java反射机制深度解析:从原理到实战
java·开发语言·后端
华洛4 小时前
我用AI做了一个48秒的真人精品漫剧,不难也不贵
前端·javascript·后端
WZTTMoon4 小时前
Spring Boot 中Servlet、Filter、Listener 四种注册方式全解析
spring boot·后端·servlet
standovon4 小时前
Spring Boot整合Redisson的两种方式
java·spring boot·后端
Cosolar5 小时前
LlamaIndex RAG 本地部署+API服务,快速搭建一个知识库检索助手
后端·openai·ai编程
IAUTOMOBILE5 小时前
Python 流程控制与函数定义:从调试现场到工程实践
java·前端·python
MX_93595 小时前
SpringMVC请求参数
java·后端·spring·servlet·apache
忆想不到的晖6 小时前
Codex 探索:别急着调 Prompt,先把工作流收住
后端·agent·ai编程
weixin_408099676 小时前
【实战对比】在线 OCR 识别 vs OCR API 接口:从个人工具到系统集成该怎么选?
图像处理·人工智能·后端·ocr·api·图片文字识别·文字识别ocr