深入理解 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方法做了什么 如何完成反序列化及数据校验

相关推荐
上进小菜猪6 小时前
把 KES 集群交给 Kubernetes 的九十天:一个 DBA 的试用实录
后端
两点王爷7 小时前
PostgreSQL 常用 SQL 语句与 GIS 相关函数详解
数据库·后端
麻雀飞吧7 小时前
先判断工具用来学习、开发还是执行
人工智能·python
考虑考虑8 小时前
Springboot环境变量占位符语法
spring boot·后端·spring
人邮异步社区8 小时前
学习Python的最佳学习路径是什么?
python·程序员
步行cgn9 小时前
Spring 基于 XML 的自动装配:byName 详解
java·后端·spring
troy12810 小时前
Python 基础语法(九):Django/Flask/FastAPI 三大 Web 框架详细对比解析
python·jupyter·django·flask·github·fastapi
jzshmyt10 小时前
我用 Python 从零“生成“了一个宇宙,然后让它观察自己(v14)
人工智能·pytorch·python·numpy·matplotlib·空间计算·scipy
高洁0111 小时前
大模型的幻觉怎么治
人工智能·深度学习·django·transformer·tornado
RISCV_Explorer11 小时前
RISC-V启动与运行时规范机制解析——BRS约定、HSM多核启动与设备树要求
后端·risc-v