如何动态设置序列化程序的字段(不是在初始化期间)?

2024-04-19 03:52:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图排除嵌套序列化程序的字段。我该怎么做呢?你知道吗

例如,对于序列化程序

class UserDetailSerializer(serializers.ModelSerializer):
   user  = UserSerializer() # want to exclude fields in this serializer
   other = OtherSerializer()

   class Meta:
       model = User

它应该像

serialized = UserDetailSerializer(user_detail, exclude=['fields'])

排除值应该传递给其他序列化程序,即UserSerializer和OtherSerializer。你知道吗

我在drf文档中有一个dynamicFieldModelSerializer的修改版本,但它只适用于从它继承的类。你知道吗

class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """
    A ModelSerializer that takes an additional `fields` argument that
    controls which fields should be displayed.
    """

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)
        exclude = kwargs.pop('exclude', None)

        # Instantiate the superclass normally
        super().__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields.keys())
            for field_name in existing - allowed:
                self.fields.pop(field_name)
        elif exclude is not None:  
            # drop fields that are specified in the 'exclude' argument
            for field_name in set(exclude):
                self.fields.pop(field_name)

Tags: thenameinself程序nonefieldfields
1条回答
网友
1楼 · 发布于 2024-04-19 03:52:36

好吧,我在这里找到了解决办法: https://stackoverflow.com/a/37186932/10531996

以下是支持多值字段的编辑版本:

class NestedDynamicFieldsModelSerializer(serializers.ModelSerializer):

def __init__(self, *args, **kwargs):

    def parse_nested_fields(fields):
        field_object = {"fields": []}
        for f in fields:
            obj = field_object
            nested_fields = f.split("__")
            for v in nested_fields:
                if v not in obj["fields"]:
                    obj["fields"].append(v)
                if nested_fields.index(v) < len(nested_fields) - 1:
                    obj[v] = obj.get(v, {"fields": []})
                    obj = obj[v]
        return field_object

    def select_nested_fields(serializer, fields):
        for k in fields:
            if k == "fields":
                fields_to_include(serializer, fields[k])
            else:
                select_nested_fields(serializer.fields[k], fields[k])

    def fields_to_include(serializer, fields):
        # Drop any fields that are not specified in the `fields` argument.
        allowed = set(fields)
        if isinstance(serializer, serializers.ListSerializer):
            existing = set(serializer.child.fields.keys())
            for field_name in existing - allowed:
                serializer.child.fields.pop(field_name)
        else:
            existing = set(serializer.fields.keys())
            for field_name in existing - allowed:
                serializer.fields.pop(field_name)

    # Don't pass the 'fields' arg up to the superclass
    fields = kwargs.pop('fields', None)
    # Instantiate the superclass normally
    super(NestedDynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

    if fields is not None:
        # import pdb; pdb.set_trace()
        fields = parse_nested_fields(fields)
        # Drop any fields that are not specified in the `fields` argument.
        select_nested_fields(self, fields)

用法:

serialized = ClassSerializer(instance, fields=[
    field, 
    field2__value1, field2__value2, 
    field3__field1__value1
])

相关问题 更多 >