Django REST Framework 序列化器优化

春秋大王2025-10-1012 次阅读
Django REST Framework 序列化器优化


DRF(Django REST Framework)的序列化器是连接数据库模型与 API 响应的核心桥梁,ModelSerializer作为Serializer的子类,能自动生成与模型字段对应的序列化字段,避免手动定义每个属性,同时支持自定义字段、数据验证和关联关系处理,是实际开发中使用率超过 90% 的序列化方案。​

以图书与作者的关联模型为例,优化后的序列化器不仅能简化代码,还能通过嵌套序列化、字段权限控制等功能,满足复杂的 API 数据返回需求:

# models.py​
from django.db import models​
    # 外键关联:on_delete=models.CASCADE表示删除作者时,关联的图书也会被删除​
    author = models.ForeignKey(​
        Author, ​
        on_delete=models.CASCADE, ​
        related_name="books",  # 反向查询别名,可通过author.books获取作者的所有图书​
        verbose_name=_("作者")​
    )​
    price = models.DecimalField(​
        _("价格"), ​
        max_digits=10,  # 总位数​
        decimal_places=2,  # 小数位数​
        help_text="图书的销售价格,保留两位小数"​
    )​
    is_published = models.BooleanField(_("是否出版"), default=False)​
    created_at = models.DateTimeField(_("创建时间"), auto_now_add=True)​
​
    class Meta:​
        verbose_name = _("图书")​
        verbose_name_plural = _("图书列表")​
        indexes = [​
            # 为常用查询字段添加索引,提升查询效率​
            models.Index(fields=["title"]),​
            models.Index(fields=["author", "is_published"])​
        ]
# serializers.py​
from rest_framework import serializers​
    # 6. 字段级验证:针对单个字段进行合法性检查​
    def validate_title(self, value):​
        """验证书名长度不小于5个字符,且不包含特殊符号"""​
        if len(value) < 5:​
            raise serializers.ValidationError(_("书名长度不能少于5个字符"))​
        if any(char in '!@#$%^&*()' for char in value):​
            raise serializers.ValidationError(_("书名不能包含特殊符号"))​
        return value​
​
    # 7. 对象级验证:针对多个字段的关联验证(如出版状态与价格的关系)​
    def validate(self, data):​
        """若图书已出版,价格不能低于10元"""​
        if data.get("is_published") and data.get("price") < 10:​
            raise serializers.ValidationError(_("已出版图书的价格不能低于10元"))​
        return data​
​
    # 8. 重写创建/更新方法:添加额外业务逻辑(如记录操作日志)​
    def create(self, validated_data):​
        # 获取当前登录用户(需在视图中配置认证)​
        user = self.context["request"].user​
        # 创建图书记录​
        book = Book.objects.create(**validated_data)​
        # 记录操作日志(实际项目可使用Django信号或日志模块)​
        print(f"用户{user.username}创建了图书:{book.title}")​
        return book

在视图中使用该序列化器时,可根据请求类型自动适配字段权限:​


  • GET 请求:返回author_info、price_tag等只读字段,方便前端展示;​
  • POST/PUT 请求:仅接收title、price、author等可写字段,且经过验证逻辑确保数据合法性。