查看源代码后,我看不出有任何方法可以通过提供的专门 kwarg 轻松实现这一点。这dict
函数是递归的,不支持任意参数。
现在,我能够将一些东西组合在一起,但是……这太糟糕了。这是使用执行的pydantic==1.10.7
.
我在想我们可以在排除参数中应用一个特殊的标志值来提供一些东西来触发排除逻辑。这变得比我预期的更棘手,因为它需要了解对象的完整结构以及准确地如何索引排除的字段。列表上还发生了一些奇怪的标准化,这导致提供的值在函数调用过程中发生变化。
这是我能得到的最好的结果(警告未经过彻底测试)。我们创建一个字典,它在每次查找时返回自身,暴露__all__
作为排除字段。这将允许我们的密钥传递给每个模型,并传递给子对象进行评估。
EXCLUDED_SPECIAL_FIELDS = "exclude_special_fields"
class _ExclusionDict(dict):
def __init__(self):
super().__init__({"__all__": {EXCLUDED_SPECIAL_FIELDS: True}})
def get(self, key):
return self
ExcludeSpecial = _ExclusionDict()
class SpecialExclusionBaseModel(BaseModel):
_special_exclusions: set[str]
def dict(self, **kwargs):
exclusions = getattr(self.__class__, "_special_exclusions", None)
exclude = kwargs.get("exclude")
if exclusions and exclude and EXCLUDED_SPECIAL_FIELDS in exclude:
return {
k: v
for k, v in super().dict(**kwargs).items()
if k not in exclusions
}
return super().dict(**kwargs)
通过这个基类,我们可以提供一个名为的类字段_special_exclusions
来指示我们想要排除哪些字段ExcludeSpecial
实例提供为exclude
kw 参数。
在一些初步测试中,这似乎适用于嵌套层次结构,包括字典和列表。这里可能存在需要解决的错误,但希望这对其他人来说是一个很好的起点。
class MyModel(SpecialExclusionBaseModel):
_special_exclusions = {"field"}
field: str
class AnotherModel(BaseModel):
models: list[MyModel]
class AnotherAnotherModel(BaseModel):
models: dict[str, AnotherModel]
model = MyModel(field=1)
another = AnotherAnotherModel(models={"test": AnotherModel(models=[model])})
print(another.dict(exclude=ExcludeSpecial))
{'models': {'test': {'models': [{}]}}}