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

相关推荐
程序员敲代码吗2 小时前
探索数字转换与计算机存储基础
前端·python
chushiyunen2 小时前
django日志使用笔记
数据库·笔记·django
tant1an2 小时前
Spring Boot 进阶之路:热部署机制 + 配置高级特性详解
java·spring boot·后端
深蓝电商API2 小时前
汽车之家车型参数对比表爬取
爬虫·python
xiaoye37082 小时前
如何在Spring中使用注解解决线程并发问题?
java·后端·spring
future02102 小时前
Spring IOC启动全流程解密
java·后端·spring·ioc
codeJinger2 小时前
【Python】集合
开发语言·python
威联通安全存储2 小时前
严谨性的数字基石:某精密医疗器械企业基于威联通的数据治理实践
运维·数据库·python
太阳神LoveU2 小时前
Spring Boot 4.0.3和3.X的各个版本主要功能差别和优劣势对比
java·spring boot·后端