当前位置: 首页 > news >正文

Django REST Framework Serializer 进阶教程

1. 序列化器概述

在 Django REST Framework(DRF)中,序列化器(Serializer)用于将复杂的数据类型(如模型实例)转换为 JSON 格式,以便于 API 返回给客户端。此外,序列化器还可以用于验证请求数据。

2. 基本的 ModelSerializer 使用

  1. 在 models.py 中定义了一个 Department 模型,用来表示部门的信息。在这个模型中,我们包括了 full_name 字段(存储部门的完整名称),以及 level 字段(表示部门的层级)。
# models.py
from django.db import modelsclass Department(models.Model):# 部门的全名,使用 `CharField` 存储full_name = models.CharField(max_length=255)# 部门的层级,默认为 0level = models.IntegerField(default=0)def __str__(self):return self.full_name
  1. ModelSerializerSerializer 的一个子类,专门用于将 Django 模型实例转化为 JSON 格式,且支持自动化字段映射。
例子:
from rest_framework import serializers
from .models import Departmentclass DepartmentSerializer(serializers.ModelSerializer):class Meta:model = Departmentfields = '__all__'

这里,DepartmentSerializer 会自动根据 Department 模型的字段生成相应的序列化字段。

3. 使用 SerializerMethodField 动态计算字段

SerializerMethodField 是 DRF 提供的一种特殊字段类型,用于动态计算某个字段的值。你可以定义一个方法,方法名称是 get_<field_name>,该方法会自动被调用来计算字段的值。

示例:

假设 Department 模型有一个字段 full_name,表示部门的全名(例如:“公司-技术-后端”),我们希望计算一个 level 字段,表示该部门的层级。

from rest_framework import serializersclass DepartmentSerializer(serializers.ModelSerializer):# level 字段会动态计算level = serializers.SerializerMethodField(read_only=True)class Meta:model = Departmentfields = '__all__'# 动态计算 level 字段def get_level(self, obj):full_name = obj.full_name# 按照 '-' 分割 full_namefull_name_split = full_name.split('-')# 计算层级:忽略第一个部分(例如“公司”)return len(full_name_split) - 1

在这个示例中:

  • level 字段是一个 SerializerMethodField,它不会直接从模型中读取,而是通过 get_level 方法动态计算。
  • get_level 方法接收 obj(即当前的 Department 实例),根据 full_name 字段来计算层级。
  • full_name.split('-') 会将部门的全名拆分为多个部分,然后计算层级。

4. 使用自定义 __init__ 方法动态控制字段

有时,我们可能需要根据外部条件来动态修改序列化器中的字段。例如,某些字段可能在某些情况下不需要序列化。我们可以通过重写 __init__ 方法来实现这一点。

示例:
class DepartmentSerializer(serializers.ModelSerializer):level = serializers.SerializerMethodField(read_only=True)def __init__(self, *args, **kwargs):fields = kwargs.pop('fields', [])super().__init__(*args, **kwargs)if fields:# 删除未指定的字段allowed = set(fields)existing = set(self.fields)for field_name in existing - allowed:self.fields.pop(field_name)def get_level(self, obj):full_name = obj.full_namefull_name_split = full_name.split('-')return len(full_name_split) - 1class Meta:model = Departmentfields = '__all__'depth = 1read_only_fields = ('id',)

在上面的代码中:

  • __init__ 方法接受一个 fields 参数,该参数是一个字段列表,表示要包含的字段。
  • 如果 fields 参数不为空,它会从已有的字段中删除未指定的字段,从而控制序列化器返回的字段。

5. 实战案例:使用 SerializerMethodField 和自定义字段控制

背景:

假设我们要设计一个 API,返回部门的层级结构,并且根据不同的条件返回不同的字段。我们需要动态计算部门的层级,并且能够根据请求控制返回哪些字段。

模型:
# models.py
from django.db import modelsclass Department(models.Model):full_name = models.CharField(max_length=255)level = models.IntegerField(default=0)def __str__(self):return self.full_name
视图:
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Department
from .serializers import DepartmentSerializerclass DepartmentView(APIView):def get(self, request):# 假设我们根据参数决定返回哪些字段fields = request.query_params.getlist('fields', [])# 获取所有部门数据departments = Department.objects.all()# 使用序列化器返回数据serializer = DepartmentSerializer(departments, many=True, fields=fields)return Response(serializer.data, status=status.HTTP_200_OK)
URL 配置:
# urls.py
from django.urls import path
from .views import DepartmentViewurlpatterns = [path('departments/', DepartmentView.as_view(), name='departments-list'),
]

6. 测试:

假设我们有以下部门数据:

full_namelevel
公司-技术-后端2
公司-财务1
公司-人力资源1
请求 1:返回所有字段
GET /departments/

返回:

[{"full_name": "公司-技术-后端","level": 2},{"full_name": "公司-财务","level": 1},{"full_name": "公司-人力资源","level": 1}
]
请求 2:仅返回 full_namelevel 字段
GET /departments/?fields=full_name&fields=level

返回:

[{"full_name": "公司-技术-后端","level": 2},{"full_name": "公司-财务","level": 1},{"full_name": "公司-人力资源","level": 1}
]

7. 总结

  • SerializerMethodField:用来动态计算字段的值,可以根据模型实例的内容或请求参数来决定字段的值。
  • get_<field_name> 方法:定义字段的计算逻辑。
  • 动态字段控制:通过在序列化器的 __init__ 方法中动态修改字段来控制序列化器返回哪些字段。
  • 实战案例:通过 fields 参数控制返回字段,并动态计算层级。

这个案例展示了如何在 Django REST Framework 中灵活地使用序列化器来动态计算和控制返回字段,适用于多种 API 场景。


文章转载自:

http://1mRSoVUb.gbnbm.cn
http://IsqIbdAJ.gbnbm.cn
http://JgyliaFD.gbnbm.cn
http://K7eluPHX.gbnbm.cn
http://Ad1SpHgs.gbnbm.cn
http://WvVJoou4.gbnbm.cn
http://FbJfpGfD.gbnbm.cn
http://8DgnbJ8V.gbnbm.cn
http://9C67qnqP.gbnbm.cn
http://cNb7qAq5.gbnbm.cn
http://EjHAJAEU.gbnbm.cn
http://Glv4ott8.gbnbm.cn
http://XYyFgzIb.gbnbm.cn
http://Irlkf9qU.gbnbm.cn
http://NWvCSkiR.gbnbm.cn
http://fJuJVceY.gbnbm.cn
http://nKMRwcDh.gbnbm.cn
http://y0nVbUEv.gbnbm.cn
http://Xz38HCBC.gbnbm.cn
http://SsiTWkfT.gbnbm.cn
http://OoxYQMYv.gbnbm.cn
http://MuflmxGx.gbnbm.cn
http://9BwpfvSG.gbnbm.cn
http://A1NYtlWb.gbnbm.cn
http://qZPTQuCa.gbnbm.cn
http://kyqvYfHY.gbnbm.cn
http://oQF5BpwP.gbnbm.cn
http://hBFgCXyK.gbnbm.cn
http://oqKCPhC5.gbnbm.cn
http://N57pgOjQ.gbnbm.cn
http://www.dtcms.com/a/364243.html

相关文章:

  • 少儿舞蹈小程序(6)打造您的“活”名片:动态展示机构实力
  • lesson53:CSS五种定位方式全解析:从基础到实战应用
  • 20250901 搜索总结
  • C语言中的运算符
  • vue3 使用css变量
  • CSS Sass Less 样式.xxx讲解
  • 代码随想录算法训练营第四天|链表part02
  • Windows 10/11 系统 vcruntime140.dll 故障终极解决:从重装组件到系统修复的完整流程
  • 飞算JavaAI真能帮小白搞定在线图书借阅系统?开发效果大揭秘!
  • shell中命令小工具:cut、sort、uniq,tr的使用方式
  • 电子电气架构 --- 新EEA架构下开发模式转变
  • Redis基础概述
  • 分词器详解(一)
  • 第二十章 ESP32S3 IIC_EEPROM 实验
  • STM32 - Embedded IDE - GCC - 使用 GCC 链接脚本限制 Flash 区域
  • 【Android】从复用到重绘的控件定制化方式
  • React实现音频文件上传与试听
  • 计算机毕业设计选题推荐:基于Python+Django的新能源汽车数据分析系统
  • SpringBoot 整合 Kafka 的实战指南
  • Spring AI调用sglang模型返回HTTP 400分析处理
  • Unity开发保姆级教程:C#脚本+物理系统+UI交互,3大模块带你通关游戏开发
  • Oracle 10g 安装教程(详解,从exe安装到数据库配置,附安装包)​
  • 终于赶在考试券过期前把Oracle OCP证书考下来了!
  • 使用 PHP Imagick 扩展实现高质量 PDF 转图片功能
  • 字节跳动把AI大模型入门知识点整理成手册了,高清PDF开放下载
  • 嵌入式解谜日志-网络编程(udp,tcp,(while循环原理))
  • 【C语言指南】回调函数:概念与实际应用的深度剖析
  • 深度学习——基于卷积神经网络实现食物图像分类之(保存最优模型)
  • leetcode-每日一题-人员站位的方案数-C语言
  • 基于飞算JavaAI的在线图书借阅平台设计与实现