SerializerMethodField
这是一个只读字段。它通过调用它所连接的序列化类的方法来获得它的值。它可用于将任何类型的数据添加到对象的序列化表示中。
签名: SerializerMethodField(method_name=None)
- method_name - 要调用序列化对象的方法的名称。如果不包含,则默认为 get_<field_name>.
由 method_name 参数引用的序列化方法应该接受一个参数(除了 self),这是要序列化的对象。它应该返回你想要包含在对象的序列化表示中的任何内容。例如:
场景介绍:一个用户往往对应多个角色,而角色字段并不在UserProfile表中,这就需要我们新增角色字段到user序列化中
from .models import UserProfile
from .models import UserRole
class UserProfileSerializer(serializers.ModelSerializer):
"""
show list serializer
"""
role = serializers.SerializerMethodField()
class Meta:
model = UserProfile
# fields = "__all__"
fields = ["id", "username","role", "account", "really_name", "department", "tel_phone",
"create_time", "email", "last_time", "creator"]
def get_role(self,obj):
user_id = obj.id
roles = [i.role.name for i in UserRole.objects.filter(user_id=user_id)]
roles = ",".join(roles)
return roles
相反的场景:我们提交的表单数据存在于多表中(因为表中含有多对多字段),如何验证所有字段,并保存完整的数据到各表中。
刚开始的思路在ModelSerializer中新增未定义字段,然后发现这并不可行。我也犯了SerializerMethodField的错误,但随后去读了serializer的源码,以及了解serializer的顺序,就知道SerializerMethodField仅用于list方法。
问题的突破点到底在哪里呢,在drf serializer 官方文档中就有一个知识点,serializer.save(**kwargs),kwargs数据被绑定在serializer.validated_data对象上,当create或update的时候就会被添加进数据库,相当于validated_data.update(kwargs)
实际源码不是这样子,但也就是这么个意思。
重写Serializer create,update方法
from rest_framework.utils import model_meta
def create(self, validated_data):
field= validated_data.pop('field_name')
validated_data = validated_data
instance = Model.objects.create(**validated_data)
# ...外键表的操作
return instance
def update(self, instance, validated_data):
field= validated_data.pop('field_name')
info = model_meta.get_field_info(instance)
for attr, value in validated_data.items():
if attr in info.relations and info.relations[attr].to_many:
field = getattr(instance, attr)
field.set(value)
else:
setattr(instance, attr, value)
instance.save()
# ...
return instance