Django REST Framework 自定义字段与序列化器高级用法一
Django REST Framework 自定义字段与序列化器高级用法总结
一、自定义字段类 MyField
- 继承关系
继承自 serializers.IntegerField,基础类型为整数字段
实现了自定义字段的完整生命周期管理 - 核心方法解析
init 方法
def __init__(self, method_name=None, **kwargs):
self.method_name = method_name # 自定义方法名
super().__init__(**kwargs) # 调用父类初始化
允许传入 method_name 参数指定获取值的方法名
保留父类所有参数传递能力
bind 方法
def bind(self, field_name, parent):
if self.method_name is None:
self.method_name = "get_{field_name}".format(field_name=field_name)
super().bind(field_name, parent)
自动设置默认方法名格式为 get_<字段名>
建立字段与父序列化器的关联关系
get_attribute 方法
def get_attribute(self, instance):
method = getattr(self.parent, self.method_name)
return method(instance)
动态调用父序列化器上的指定方法获取字段值
实现字段值的自定义获取逻辑
to_representation 方法
def to_representation(self, value):
return str(value)
将整数值转换为字符串输出
控制序列化后的输出格式
二、模型序列化器 CreateSerializer
- 基本配置
class CreateSerializer(serializers.ModelSerializer):
gender = MyField() # 使用自定义字段
class Meta:
model = models.User # 关联的模型
fields = ["id", "username", "age", "gender", "depart"] # 包含字段
extra_kwargs = {
"id": {"read_only": True}, # 只读字段
"age": {"write_only": True} # 只写字段
}
继承 ModelSerializer 自动生成大部分字段
通过 Meta 类配置模型关联和字段行为
- 自定义方法
def get_gender(self, obj):
return obj.get_gender_display()
实现 get_<字段名> 格式的方法
调用模型的 get_
三、API视图 CreateUserView
- 请求处理流程
def post(self, request, *args, **kwargs):
print(request.data, type(request.data)) # 调试打印原始数据
ser = CreateSerializer(data=request.data) # 初始化序列化器
if ser.is_valid(): # 数据验证
print(ser.validated_data) # 打印验证后数据
ser.save() # 自动调用create或update
return Response(ser.data) # 返回序列化数据
else:
print("视图", ser.errors) # 打印错误信息
return Response(ser.errors) # 返回错误响应
- 关键点说明
数据验证:is_valid() 触发所有字段验证逻辑
数据保存:save() 自动根据实例状态调用正确方法
响应返回:成功返回序列化数据,失败返回错误详情
四、技术要点总结
自定义字段实现:
继承DRF基础字段类
重写关键方法控制字段行为
支持动态方法调用
模型序列化器高级用法:
混合使用自动生成字段和自定义字段
通过 extra_kwargs 精细化控制字段属性
自定义方法扩展字段功能
这种实现方式展示了DRF的高度灵活性,通过自定义字段可以处理各种复杂的数据转换需求,同时保持了ModelSerializer的便利性。
五、整体代码展示:
class MyField(serializers.IntegerField):
def __init__(self, method_name=None, **kwargs):
self.method_name = method_name
super().__init__(**kwargs)
def bind(self, field_name, parent):
if self.method_name is None:
self.method_name = "get_{field_name}".format(field_name=field_name)
super().bind(field_name, parent)
def get_attribute(self, instance):
method = getattr(self.parent, self.method_name)
return method(instance)
def to_representation(self, value):
return str(value)
class CreateSerializer(serializers.ModelSerializer):
gender = MyField()
class Meta:
model = models.User
fields = ["id", "username", "age", "gender", "depart"]
extra_kwargs = {
"id": {"read_only": True},
"age": {"write_only": True}
}
def get_gender(self, obj):
return obj.get_gender_display()
class CreateUserView(APIView):
def post(self, request, *args, **kwargs):
print(request.data, type(request.data))
ser = CreateSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data)
ser.save()
return Response(ser.data)
else:
print("视图", ser.errors)
return Response(ser.errors)
浙公网安备 33010602011771号