首页 > 解决方案 > 列出 Django Rest Framework 序列化程序中所需字段的名称(并忽略父字段)

问题描述

我要做的是获取序列化程序中所有字段的列表:

例如,如果我有像这样的序列化程序:

class ParentSerializer(serializers.Serializer):
    parent_field = serializers.IntegerField

class ChildSerializer(ParentSerializer):
    child_field_required = serializers.IntegerField
    child_field_not_required = serializers.IntegerField(required=False) 

我希望得到的输出是:

['child_field_required']

我发现我可以获得已声明字段的有序列表,例如:

self.get_serializer().get_fields()
>> OrderedDict([
       ('parent_field', IntegerField()),
       ('child_field_required', IntegerField()),
       ('child_field_not_required', IntegerField(required=False)),
])

但我一直无法超越这一步。

标签: djangoserializationdjango-rest-framework

解决方案


由于您继承自serializers.Serializer,因此必须在类主体上显式声明所有字段(与serializers.ModelSerializer遍历模型层以自动生成字段不同)。在这种情况下,您可以这样做:

parent_field_names = {
    name
    for base in type(instance).__bases__
    if hasattr(base, '_declared_fields')
    for name in base._declared_fields
}
desired_fields = [
    (name, field)
    for name, field in instance.get_fields().items()
    if name not in parent_field_names and
    field._kwargs.get('required', None) is not False
]

假设instance是一个serializers.Serializer实例。parent_field_names指的是 O(1) 查找的集合。

以上取决于几个实现细节

  • serializers.Serializer--的元类serializers.SerializerMetaclass将声明的字段分配为类属性_declared_fieldsdict
  • 整个构造(__new__),serializers.Field该类将最初传递的关键字参数作为_kwargs实例上的属性保留给新创建的字段实例

笔记:

  • 如果您想让它也适用于serializers.ModelSerializer的模型字段遍历,即对于未声明的字段或覆盖的字段Meta,您需要检查get_fields每个字段,然后仅获取当前序列化程序中定义的字段

  • serializers.SerializerMetaclass pop_declared_fields在创建属性时从类属性中关闭字段,因此您无法访问类中的字段。否则,我们可以在基类上使用属性检查来查看是否在那里定义了任何字段,这将导致代码更短。


推荐阅读