我正在使用 pydantic 1.3 来验证我正在编写的 API 的模型。
在继承自
pydantic.BaseModel
的类中包含任意方法是否常见/良好实践?
我需要一些与对象,我正在尝试决定是否需要一个“处理程序”类。这些模型正在转换为 JSON 并发送到我也在编写的一个宁静的服务。
我的模型看起来像这样:
class Foo(pydantic.BaseModel):
name: str
bar: int
baz: int
这样做是不是不好的做法:
class Foo(pydantic.BaseModel):
name: str
bar: int
baz: int
def add_one(self):
self.bar += 1
这对我来说有些道理,但我找不到任何人这样做的例子。
在 Pydantic 模型中包含非验证方法 并非天生就是坏事 ,但这 通常表明你的模型承担了过多的责任,可能需要重新设计 。
为什么在 Pydantic 模型中使用非验证方法可能不合适?
- 关注点分离: Pydantic 模型主要用于数据验证和序列化。将其他业务逻辑添加到其中会模糊其主要目的,并可能导致难以测试和维护的臃肿模型。
- 意外副作用: 在验证上下文中调用非验证方法可能会导致意外的副作用,特别是在你希望 Pydantic 处理数据完整性的情况下。
- 替代方案: 通常,可以使用更清晰、更易于测试的模式来实现相同的结果,例如使用单独的函数或服务类来处理业务逻辑。
何时在 Pydantic 模型中使用非验证方法可能是可以接受的?
- 派生属性: 如果某个方法计算基于模型属性的派生值而没有副作用,那么将其包含在模型中可能是合理的。
- 格式化辅助函数: 用于特定格式(例如,用于 API 响应的自定义 JSON 表示形式)准备数据的简单帮助器方法有时可以放在模型中,以提高便利性。
关于你的具体示例
add_one
方法修改模型的状态。这最好作为模型外部的单独函数或方法来处理。例如:
def add_one_to_bar(foo: Foo) -> Foo:
"""将 foo.bar 增加 1 并返回更新后的 Foo 实例。"""
return foo.copy(update={"bar": foo.bar + 1})
# ... 后续代码 ...
foo = Foo(name="MyFoo", bar=2, baz=5)
updated_foo = add_one_to_bar(foo)
此方法将业务逻辑与数据模型分离,从而提高了代码的可读性和可维护性。
总之
虽然在 Pydantic 模型中包含非验证方法并非严格禁止,但在这样做之前,请仔细考虑你的设计选择。通常,存在更清晰、更易于维护的替代方案可以更好地分离关注点并防止意外的副作用。如果选择在模型中包含非验证方法,请确保它们服务于明确的目的并且不会引入不必要的复杂性。
标签:python,validation,design-patterns,model,pydantic From: 60047685