zoukankan      html  css  js  c++  java
  • 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
    
  • 相关阅读:
    【Codeforce 487E】【UOJ#30】—Tourists(圆方树+树链剖分)
    【省选模拟】—River(贪心)
    【BZOJ4012】【HNOI2015】—开店(动态点分治)
    【BZOJ4543】【POI2014】Hotel加强版(长链剖分)
    【BZOJ3809】—GTY的二逼妹子序列(莫队+权值分块)
    【BZOJ2878】【NOI2012】—迷失游乐园(基环树期望dp)
    【2019省选模拟】—树(并查集+容斥)
    【BZOJ2120】—数颜色(带修莫队)
    【BZOJ3597】【SCOI2014】—方伯伯运椰子(分数规划)
    【BZOJ3598】【SCOI2014】方伯伯的商场之旅(数位dp)
  • 原文地址:https://www.cnblogs.com/zenan/p/10735554.html
Copyright © 2011-2022 走看看