Python Django Rest框架中具有动态字段的列表序列化程序

Python Django Rest框架中具有动态字段的列表序列化程序,python,django,django-rest-framework,Python,Django,Django Rest Framework,我试图通过覆盖\uuu init\uu方法,将字段动态添加到Django Rest框架的序列化程序中。该方法与此处描述的方法类似: 我这样做的原因是,因为我想动态地将字段类型更改为一个,由要序列化的实例的属性type\uu确定。如果我一次序列化一个实例,这将非常有效: from rest_framework import serializers from rest_framework.fields import empty class VariableDetails: def __i

我试图通过覆盖
\uuu init\uu
方法,将字段动态添加到Django Rest框架的序列化程序中。该方法与此处描述的方法类似:

我这样做的原因是,因为我想动态地将字段类型更改为一个,由要序列化的实例的属性
type\uu
确定。如果我一次序列化一个实例,这将非常有效:

from rest_framework import serializers
from rest_framework.fields import empty


class VariableDetails:
    def __init__(self, name, type_, value):
        self.name = name
        self.type_ = type_
        self.value = value


class VariableDetailSerializer(serializers.Serializer):
    TYPE_FIELD_MAP = {
        'string': serializers.CharField,
        'integer': serializers.IntegerField,
        'float': serializers.FloatField,
    }

    name = serializers.CharField()
    type_ = serializers.CharField()

    def __init__(self, instance=None, data=empty, **kwargs):
        # this is where the magic happens
        super().__init__(instance, data, **kwargs)
        if instance is not None:
            field_type = self.TYPE_FIELD_MAP[instance.type_]
            self.fields['value'] = field_type()

string_details = VariableDetails('character value', 'string', 'hello world')
integer_details = VariableDetails('integer value', 'integer', 123)

print(VariableDetailSerializer(string_details).data)
# {'name': 'character value', 'type_': 'string', 'value': 'hello world'}

print(VariableDetailSerializer(integer_details).data)
# {'name': 'integer value', 'type_': 'integer', 'value': 123}
如果我想序列化与父实例相关的
VariableDetails
的多个实例(例如称之为
parent
),则缺少值字段:

class Parent:
    def __init__(self, variable_details):
        self.variable_details = variable_details


class ParentSerializer(serializers.Serializer):
    variable_details = VariableDetailSerializer(many=True)


parent = Parent(variable_details=[string_details, integer_details])
print(ParentSerializer(parent).data)
# {
#     'variable_details': [
#         {
#             'name': 'character_value',
#             'type_': 'string'
#             # value is missing
#         },
#         {
#             'name': 'integer_value',
#             'type_': 'integer'
#         },
#     ]
# }
显然
VariableDetailSerializer.\uuuu init\uuuu
仅在创建
ParentSerializer
期间调用,并且在初始化
ParentSerializer
的新实例时调用一次。在这两种情况下,
实例
都是
。因此,不会对每个
变量详细信息
调用它

是否有人知道如何将字段动态添加到同样正在序列化列表实例的
序列化程序中

为了便于运行代码,我创建了一个要点:
如果安装了Django Rest框架,那么代码应该可以复制和复制到python repl中。但是,您不需要创建Django项目,因为
VariableDetailSerializer
嵌套在
ParentSerializer
中,其行为类似于字段本身。在这种情况下,您可以重写
to_representation()
方法来进行动态类型切换

def to_representation(self, instance):
    field_type = self.TYPE_FIELD_MAP[instance.type_]
    self.fields['value'] = field_type()
    try:
        del self._readable_fields  # Clear the cache
    except AttributeError:
        pass
    return super().to_representation(instance)
这里的主要问题是序列化程序缓存字段,因为它不希望字段在实例之间发生更改。因此,有必要使用
del self.\u readable\u字段
清除缓存

当我将上述内容添加到
VariableDetailSerializer
并运行您的示例时,我得到:

{
    'variable_details': [
        OrderedDict([('name', u'character value'), 
                     ('type_', u'string'), 
                     ('value', u'hello world')]), 
        OrderedDict([('name', u'integer value'), 
                     ('type_', u'integer'), 
                     ('value', 123)])
    ]
}