在 Django Rest Framework 序列化程序中列出必填字段的名称(并忽略父字段)



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

  • 不要包含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.SerializerMetaclasspop类属性中的字段,因此无法访问类中的字段。 否则,我们可以对基类使用属性检查来查看其中是否定义了任何字段,这将导致代码更短。

我想出了一个解决方案,但我觉得那里有一个更优雅的解决方案......

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]

相关内容

  • 没有找到相关文章

最新更新