在使用django restframework serializer 序列化在django中定义的model时,有时候我们需要额外在serializer中增加一些model中没有的字段。有两种方法实现这个目的。
假设现在有一个Animal模型,其中有name, type, country字段,country为外键。我们在序列化Animal时,需要额外增加外键country的area信息。
方法一修改数据库,利用model 这里就不多解释,主要来说第二种,不修改django的model,直接使用SerializerMethodField(method_name=None)字段。
class AnimalSerializer(serializers.ModelSerializer): country_area = serializers.SerializerMethodField() class Meta: model = Animal fields = ('id', 'name', 'type','country','country_area') def get_country_area(self, obj): return obj.country.area
SerializerMethodFiel是一个read-only字段
当不指定其method_name时,默认为get_field_name
如果使用ModelSerializer并指定字段时,要包含此时定义的字段
补充知识:django restframework Serializer field
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
以上这篇django restframework serializer 增加自定义字段操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]