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



我正在尝试排除嵌套序列化程序的字段。我该怎么做?

例如,对于序列化程序

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'])

排除值应传递到其他序列化程序,即用户序列化程序和其他序列化程序。

我在drf文档中有一个DynamicFieldsModelSerializer的修改版本,但它仅适用于从它继承的类。

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)

好的,我在这里找到了解决方案: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
])

最新更新