You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django DRF中read_only_fields对自定义序列化字段不生效原因咨询

问题原因

DRF 的 ModelSerializer 中,Meta.read_only_fields 配置的作用范围仅包含从模型映射生成的原生字段,不覆盖你在序列化器类中显式声明的自定义字段。

DRF 处理 ModelSerializer 字段的逻辑顺序是:

  1. 根据 Meta.model 和 Meta.fields 配置,生成所有需要的模型原生字段,默认继承模型定义的字段属性
  2. 读取你在序列化器类中显式声明的所有自定义字段,直接加入字段列表,字段属性完全以你声明时传入的参数为准
  3. 最后应用 Meta.read_only_fields、Meta.extra_kwargs 等配置,仅修改第一步生成的模型原生字段的属性,不会改动第二步加入的自定义字段

对应场景解释

  • 第一种写法:owner_email、breed_name 是你显式声明的自定义字段,声明时没有传 read_only=True,默认是可写状态,read_only_fields 配置无法修改这两个字段的属性,所以接口表单里会显示可输入的输入框
  • 第二种写法:你在声明自定义字段时直接传入了 read_only=True,字段属性直接生效,所以表单会隐藏这两个字段
  • 第三种写法:name 是模型原生字段,不是你显式声明的,所以 read_only_fields 配置可以正常修改它的只读属性,符合预期

补充优化方案

如果你有多个自定义只读字段不想逐个加 read_only=True,可以在序列化器的 __init__ 方法里批量修改,示例如下:

class PetSerializer(serializers.ModelSerializer):
    owner_email = serializers.CharField(source='owner.email')
    breed_name = serializers.CharField(source='breed.str')
    class Meta:
        model = Pet
        fields = "__all__"
        read_only_fields = ["breed_name","owner_email"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field_name in self.Meta.read_only_fields:
            if field_name in self.fields:
                self.fields[field_name].read_only = True

内容的提问来源于stack exchange,提问作者Santhosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 10:54:04