Django REST Framework:继承时如何动态修改字段名称
实现可动态修改名字段的Serializer基类
核心思路
利用Python的__init_subclass__特性,在子类继承基类时自动生成指定名称的名字段,同时让基类的验证逻辑动态适配子类的字段名,彻底复用原有验证逻辑,无需重复编写。
修改后的基类代码
from rest_framework import serializers class Person(serializers.Serializer): # 子类可重写该属性,自定义名字段的名称 _name_field_name = "name" other_fields = serializers.CharField() # 示例其他固定字段 def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) # 动态为子类添加自定义名字段 setattr(cls, cls._name_field_name, serializers.CharField()) # 移除基类默认的name字段,避免字段冲突 if hasattr(cls, "name"): delattr(cls, "name") def validate(self, attrs): # 动态获取当前子类的名字段名称 name_field = self._name_field_name name_value = attrs.get(name_field) # 复用原有的联合验证逻辑,替换为动态字段名 if not name_value: raise serializers.ValidationError(f"{name_field} 不能为空") if name_value == attrs.get("other_fields"): raise serializers.ValidationError(f"{name_field} 不能与other_fields值相同") return attrs
子类实现
只需重写_name_field_name属性即可,无需额外编写验证代码:
class John(Person): _name_field_name = "john_name"
效果验证
当接收请求载荷{"john_name": "john", "other_fields": "test"}时,John序列化器会自动验证john_name字段,完全复用Person基类的验证逻辑。
兼容原有基类的简化方案
如果无法大幅修改原有基类结构,也可以通过子类手动调整字段映射:
class Person(serializers.Serializer): name = serializers.CharField() other_fields = serializers.CharField() def validate(self, attrs): # 优先使用子类指定的名字段,默认用name name_key = getattr(self, "_name_field", "name") name_value = attrs.get(name_key) if not name_value: raise serializers.ValidationError("名字段不能为空") if name_value == attrs.get("other_fields"): raise serializers.ValidationError("名字段不能与other_fields值相同") return attrs class John(Person): # 移除基类的name字段 name = None # 添加自定义字段 john_name = serializers.CharField() # 指定当前子类的名字段映射 _name_field = "john_name"
内容的提问来源于stack exchange,提问作者fsimoes
相关产品推荐
相关产品推荐

