我要做的是获取序列化程序中所有字段的列表,其中:
-
不要包含
required=False
作为参数。 - 不要来自父序列化程序。
例如,如果我有这样的序列化程序:
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)),
])
但是我无法跨过这一步。
由于您固有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_fields
类属性- 整个构造(
__new__
(,serializers.Field
类将最初传递的关键字参数保留为实例上的_kwargs
属性到新创建的字段实例
笔记:
如果你想使这也适用于
serializers.ModelSerializer
的模型字段遍历,即对于未声明的字段或在Meta
中覆盖的字段,你需要检查每个字段的get_fields
,然后只获取当前序列化程序中定义的字段创建
_declared_fields
属性时,serializers.SerializerMetaclass
pop
类属性中的字段,因此无法访问类中的字段。 否则,我们可以对基类使用属性检查来查看其中是否定义了任何字段,这将导致代码更短。
我想出了一个解决方案,但我觉得那里有一个更优雅的解决方案......
instance = ChildSerializer()
serializer_fields = instance.get_fields()
parent_serializer_fields = instance.__class__.__bases__[0]().get_fields()
child_fields = {k: serializer_fields[k] for k in set(serializer_fields) - set(parent_serializer_fields)}
required_fields = [k for k, v in child_fields.items() if v.required]