• django rest framework serializer 增加自定义字段


    需求:在使用django rest framework serializer在model 中定义的model时,当需要额外在serializer中增加一些model中没有的字段。

    方法一修改数据库,利用model,在这就不详细说了。

    方法二,不修改django的model,直接使用SerializerMethodField(method_name=None)

    假设我们现在有一个Animal模型,其中有name,type,country字段,其中country是外键。在序列化Animal时,需要额外增加country的area信息

    1. class AnimalSerializer(serializers.ModelSerializer):
    2. country_area = serializers.SerializerMethodField()
    3. class Meta:
    4. model = Animal
    5. fields = ('id','name','type','country','country_area')
    6. def get_country_area(self,obj):
    7. return obj.country.area

    SerializerMethodField是read-only字段,当不指定其method_name时,默认为get_field_name;如果使用ModelSerializer并指点字段时,要包含此时定义的字段。

    补充知识:django restframework Serializer field

    SerializerMethodField

    这是一个只读字段。它通过调用它所连接的序列化类的方法来获得它的值。它可用于将任何类型的数据添加到对象的序列化表示中。

    签名: SerializerMethodField(method_name=None)

    method_name - 要调用序列化对象的方法的名称。如果不包含,则默认为 get_.

    由 method_name 参数引用的序列化方法应该接受一个参数(除了 self),这是要序列化的对象。它应该返回你想要包含在对象的序列化表示中的任何内容。例如:

    场景介绍:一个用户往往对应多个角色,而角色字段并不在UserProfile表中,这就需要我们新增角色字段到user序列化中

    1. from .models import UserProfile
    2. from .models import UserRole
    3. class UserProfileSerializer(serializers.ModelSerializer):
    4. """
    5. show list serializer
    6. """
    7. role = serializers.SerializerMethodField()
    8. class Meta:
    9. model = UserProfile
    10. # fields = "__all__"
    11. fields = ["id", "username","role", "account", "really_name",
    12. "department", "tel_phone", "create_time", "email",
    13. "last_time", "creator"]
    14. def get_role(self,obj):
    15. user_id = obj.id
    16. roles = [i.role.name for i in UserRole.objects.filter(user_id=user_id)]
    17. roles = ",".join(roles)
    18. 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方法

    1. from rest_framework.utils import model_meta
    2. def create(self, validated_data):
    3. field= validated_data.pop('field_name')
    4. validated_data = validated_data
    5. instance = Model.objects.create(**validated_data)
    6. # ...外键表的操作
    7. return instance
    8. def update(self, instance, validated_data):
    9. field= validated_data.pop('field_name')
    10. info = model_meta.get_field_info(instance)
    11. for attr, value in validated_data.items():
    12. if attr in info.relations and info.relations[attr].to_many:
    13. field = getattr(instance, attr)
    14. field.set(value)
    15. else:
    16. setattr(instance, attr, value)
    17. instance.save()
    18. # ...
    19. return instance

  • 相关阅读:
    golang gin自定义数据校验器:github.com/go-playground/validator/v10
    【教程】Derby数据库安装与使用
    window 服务器 短文件名漏洞处理
    fegin调用关于session,请求头传递参数问题
    基于SSM框架流浪猫救援网站的设计与实现毕业设计源码201502
    Stream流reduce方法
    EnlightenGAN 开源代码运行问题汇总
    Hqst网络变压器读书笔记 :公司发展中的首要因素
    Java学习路线图,全套Java基础视频教程
    有趣的特性:CHECK约束
  • 原文地址:https://blog.csdn.net/wolflxiaolu/article/details/126196762