从入门到精通Django REST Framework-(三)

news/2025/2/26 22:03:50/文章来源:https://www.cnblogs.com/rxg456/p/18739808

一. 什么是 ModelSerializer?

ModelSerializer 是 Django REST Framework(DRF)提供的一个序列化器,它用于简化与 Django 模型的交互。ModelSerializer 通过自动读取 Django 模型的字段,生成对应的序列化字段,从而简化了手动编写字段的工作。它继承自 serializers.Serializer,但不同的是,它专门用于处理与 Django ORM 模型的数据交互。

二. 为什么要使用 ModelSerializer

  1. 简化代码ModelSerializer 通过自动从 Django 模型生成字段,避免了手动逐一定义每个字段的重复代码。它大大简化了序列化器的编写工作。
  2. 自动化操作ModelSerializer 提供了默认的 create()update() 方法,这些方法会自动根据模型的数据进行创建和更新。这意味着你不需要手动编写这些方法,减少了出错的概率。
  3. 与 Django ORM 紧密集成: ModelSerializer 与 Django 的 ORM 数据模型集成非常紧密,能够直接操作 Django 数据库模型,并且支持字段验证和嵌套序列化。自动继承 Model 的字段约束(如 max_length, null, unique 等)。
  4. 提高开发效率: 使用 ModelSerializer,开发人员无需手动定义字段和验证器,也无需重写 create()update() 方法,适合标准的 CRUD 操作,提升开发效率。

三. 基础用法

ModelSerializer 是为 Django 模型专门设计的序列化器,下面是基础的使用方法。

1. 定义 Django 模型

from django.db import modelsclass Book(models.Model):title = models.CharField(max_length=100)author = models.CharField(max_length=100)published_date = models.DateField()isbn_number = models.CharField(max_length=13)

2. 创建 ModelSerializer

from rest_framework import serializers
from .models import Bookclass BookSerializer(serializers.ModelSerializer):class Meta:model = Book  # 指定模型fields = '__all__'  # 包含所有字段

3. 使用ModelSerializer来序列化数据

# 进行数据的序列化
book = Book.objects.first()
serializer = BookSerializer(book)
print(serializer.data)  # 输出序列化后的数据

四. 核心配置 Meta 类详解

ModelSerializer 中最重要的部分是 Meta 类,以下是 Meta 类常见字段及其用法。

1. model

  • 作用:指定要与序列化器关联的 Django 模型。
  • 示例
class BookSerializer(serializers.ModelSerializer):class Meta:model = Book

2. fields

  • 作用:指定需要序列化的字段,可以是一个字段列表,或者 '__all__',表示包含所有字段。
  • 示例
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookfields = ['title', 'author']  # 只序列化 title 和 author 字段

3. exclude

  • 作用:排除不需要序列化的字段,不能与 fields 一起使用。
  • 示例
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookexclude = ['isbn_number']  # 排除 isbn_number 字段

4. read_only_fields

  • 作用:指定只读字段,这些字段不能被更新或创建。
  • 示例
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookread_only_fields = ['isbn_number', 'published_date']

5. write_only_fields

  • 作用:指定只写字段,不能通过序列化器读取这些字段。
  • 示例
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookwrite_only_fields = ['password']  # 仅用于写入

6. depth

  • 作用:指定嵌套序列化的深度。如果模型之间存在外键关系,可以设置 depth 来控制递归序列化的深度。
  • 示例
class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookdepth = 1  # 递归序列化嵌套对象(如外键)

7. validators

  • 作用:为模型或字段指定验证器,进行自定义验证。
  • 示例
def validate_title(value):if 'banned' in value:raise serializers.ValidationError("Title contains banned words.")return valueclass BookSerializer(serializers.ModelSerializer):title = serializers.CharField(validators=[validate_title])class Meta:model = Bookfields = ['title', 'author']

五. 高级技巧

嵌套序列化

对于有外键关系的模型,可以使用嵌套序列化器进行序列化。例如,如果 Book 模型有一个指向 Author 模型的外键,可以在 BookSerializer 中嵌套 AuthorSerializer

class AuthorSerializer(serializers.ModelSerializer):class Meta:model = Authorfields = ['name']class BookSerializer(serializers.ModelSerializer):author = AuthorSerializer()class Meta:model = Bookfields = ['title', 'author']

自定义 create()update() 方法

如果需要自定义创建和更新逻辑,可以重写 create()update() 方法。

class BookSerializer(serializers.ModelSerializer):class Meta:model = Bookfields = '__all__'def create(self, validated_data):# 自定义创建逻辑return Book.objects.create(**validated_data)def update(self, instance, validated_data):# 自定义更新逻辑instance.title = validated_data.get('title', instance.title)instance.save()return instance

批量更新

如果需要批量更新数据,可以通过序列化器的 update() 方法配合 many=True 来实现。

books = Book.objects.all()
serializer = BookSerializer(books, many=True)
# 更新逻辑

六. 常见问题

如何处理外键和多对多关系的序列化?

使用嵌套的 ModelSerializer 来处理外键关系(ForeignKey),可以通过 depth 或者手动嵌套序列化器来实现多对多关系。

如何排除模型中的某些字段?

使用 exclude 来排除不需要序列化的字段。

如何验证一个字段?

通过定义 validate_<field_name> 方法来为字段添加自定义验证逻辑。

如何让字段只读?

使用 read_only_fieldsMeta 类中标记字段为只读。

七. 生产技巧

1.性能优化

  • 对于大数据量的序列化,尽量避免使用深度过大的嵌套序列化,可以使用 depth 控制递归深度,或者使用自定义嵌套序列化器来减少不必要的嵌套。
  • 使用 select_relatedprefetch_related 预加载外键和多对多关系,避免 N+1 查询问题。

2.使用 ModelSerializer 优化 API 性能:

  • 在处理批量数据时,尽量批量创建或更新数据(例如使用 bulk_createbulk_update)。
  • 对于常用字段,可以通过缓存优化性能。

批量创建数据

from rest_framework import serializers
from django.db import transactionclass ProductBulkSerializer(serializers.ModelSerializer):class Meta:model = Productfields = ['name', 'price', 'category']@transaction.atomicdef create(self, validated_data):# 原生批量创建(跳过 ModelSerializer 的单个创建逻辑)objs = [Product(**item) for item in validated_data]return Product.objects.bulk_create(objs)# 使用方式
data = [{'name': 'A', 'price':10}, {'name':'B', 'price':20}]
serializer = ProductBulkSerializer(data=data, many=True)
serializer.is_valid(raise_exception=True)
serializer.save()

批量更新数据

class ProductBulkUpdateSerializer(serializers.ModelSerializer):id = serializers.IntegerField(required=True)class Meta:model = Productfields = ['id', 'price', 'stock']def update(self, instance, validated_data):# 原生批量更新(需配合视图逻辑)update_objs = []for item in validated_data:obj = Product.objects.get(id=item['id'])obj.price = item['price']update_objs.append(obj)Product.objects.bulk_update(update_objs, ['price'])return update_objs

3.动态修改字段required属性

  • POST请求:需要提供所有字段的值
  • PATCH请求:动态修改字段属性,允许只更新需要修改的字段
from rest_framework import serializersclass DynamicRequiredFieldsMixin:def get_fields(self):fields = super().get_fields()request = self.context.get('request', None)# 仅当请求方法为 PATCH 时调整必填性if request and request.method in ['PATCH']:for field_name, field in fields.items():field.required = False  # 所有字段变为可选field.allow_null = True # 允许传入 null(可选)return fields# 使用示例
class ProductSerializer(DynamicRequiredFieldsMixin, serializers.ModelSerializer):class Meta:model = Productfields = '__all__'

关键原理剖析

  1. Hook 机制
    • 通过重写 get_fields() 方法,在序列化器初始化时动态修改字段属性
    • 执行顺序:get_fields() → 字段实例化 → 验证逻辑
  2. 请求上下文获取
    • self.context['request'] 获取当前请求对象
    • 需确保视图将 request 传递到序列化器上下文中(通常自动处理)
  3. 字段属性动态修改
属性 作用 示例值
required 控制字段是否必须传入 False
allow_null 允许接收 null 值(需数据库允许) True

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/890385.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

洛谷2025省选模拟赛D1T1“Ball” 题解

洛谷2025省选模拟赛D1T1“Ball” 题解首先可以写出一个暴力的 dp : 令 \(f_{i,j}\) 表示有 \(i\) 个选了一次的球和 \(j\) 个选了大于一次的球的期望答案,有等式: \[f_{i,j}=\frac jnf_{i,j}+\frac{n-i-j}nf_{i+1,j}+\frac in f_{i-1,j+1} \]进一步得 \(f_{i,j}=\frac{n-i-j…

[计算机网络/网络抓包/以太网] `.pcap` 数据报文存储格式

序:一份以太网报文概述:.pcap 数据报文存储格式 简介.pcap文件:一种常用的数据报文存储格式,主要用于网络数据包的捕获和存储。pcap文件格式由PCAP库提供,支持将网络上的所有数据包保存到文件中,并可以从文件中读取数据包。 pcap文件通常由文件头和数据包头组成,每个数据…

C#/.NET/.NET Core技术前沿周刊 | 第 27 期(2025年2.17-2.23)

前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿,助力技术成长与视野拓宽。欢迎投稿、推荐或自荐优质文章、项目、学习资源等…

Jenkins详解教程

1.介绍2.Jenkins CI/CD 流程3.部署Jenkins查看初始密码4 使用Jenkins

Redis概述安装与基本数据类型

Redis概述安装与基本数据类型 1. 什么是NoSQL NoSQL( Not Only SQL ),意即不仅仅是SQL, 泛指非关系型的数据库。Nosql这个技术门类,早期就有人提出,发展至2009年趋势越发高涨。 2. NoSQL的广泛应用 随着大数据的兴起,数据量的暴增,数据类型的丰富,传统的关系数据库在应付动…

Hello! I am Zhan Yijue,nice to meet you

这个作业属于哪个课程 23软件工程这个作业要求在哪里 【作业1】自我介绍+软工5问这个作业的目标 学习使用 Markdown, 熟练掌握 GitHub 及 Git 的使用方法, 建立个人博客个人介绍 ❤️ 兴趣爱好听歌 🎧 书法📝 看书,尤其是科幻小说 📊 二次元爱好者 🎩📖 学习经历广东…

Hugging Face 发布 Python WebRTC 库:构建实时音视频应用;微软 Magma:多模态跨数字物理世界丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑…

1Panel 专业版评测:全面超越宝塔的运维面板新标杆

一、 UX体验与移动端适配:更直观的跨平台交互 1Panel 专业版在用户体验上实现了对宝塔的全面超越。其界面采用现代化设计语言,以黑金主题 为代表的可定制化主题系统支持一键切换,视觉风格更符合技术审美,同时保持功能模块的清晰布局。相较于宝塔复杂的多级菜单,1Panel 的 …

基于抖音agent平台Cozi打造Agent智能体

AI Agent 一、AI Agent(智能体)与开发平台 【1】AI Agent的概念 AI Agent直接翻译更准确,AI代理人。AI Agent是指可以自主执行任务或目标的系统,它可以是一个软件,也可以是一个智能机器,这些系统通过感知环境并在此基础上做出决策。AI Agent可以集成多种技术,包括AI大模…

纯离线部署本地知识库LLM大模型

纯离线部署本地知识库LLM大模型 一、下载离线大模型下载的网址:https://hf-mirror.com/deepseek qwen 相关的模型,只建议使用1.5B的,GGUF后缀的模型 推荐下载llama相关模型,同样是GGUF后缀的,自己笔记本电脑推荐下载8B的 二、下载大模型管理平台 LM Studio下载网址:https…

mailto链接

本文主要内容转载自Haorooms!好用的mailto网站话不多说直接上正菜! 大佬dawsbot提供的工具mailto.vercel.app前言 今天看到老外写的一篇关于mailto: HTML e-mail 的文章,感觉很新奇,以前从来没有这么用过,用email的时候,最多用过mailto,但是其中穿链接参数,还是第一次看…