Pydantic:保存嵌套设置

Pydantic: Save nested settings

我目前正在尝试在更改时自动将 pydantic.BaseSettings 对象保存到 json 文件。该模型是预先从 json-File 中加载的。保存过程的最小工作示例如下:

import json
from pydantic import BaseModel, BaseSettings, root_validator
from typing import Any, Dict


class NestedSettings(BaseModel):
    test: str = 'foobar'


class Settings(BaseSettings):
    nested: NestedSettings = NestedSettings()
    foo: str = 'bar'

    @root_validator
    def save_settings(cls, values: Dict[str, Any]) -> Dict[str, Any]:
        print('SAVING!')

        def serialize_basemodel(model: BaseModel):
            if isinstance(model, BaseModel):
                return model.dict()
            else:
                raise TypeError(f'{type(model)} is not serializable!')

        with open('config.json', 'w', encoding='utf-8') as f:
            json.dump(values, f, ensure_ascii=False, indent=2,
                      default=serialize_basemodel)
        return values

    class Config:
        validate_assignment: bool = True


s = Settings()
print('Saving top level:')
s.foo = 'baz'
print('Saving bottom level:')
s.nested.test = 'bar'

生成的输出是:

SAVING!
Saving top level:
SAVING!
Saving bottom level:

即使分配了底层 s.nested.bar,我也想让对象保存。有什么办法可以实现吗?

提前感谢任何提示!

我的回答不够优雅,但由于 validate_assignment 似乎只检查根字段,您仍然可以通过更改

来利用该操作
s.nested.test

s.nested = {'test': 'bar'}

它会起作用的。这是示例代码和输出,以便更好地演示。

class Settings(BaseSettings):
    nested: NestedSettings = NestedSettings()
    foo: str = 'bar'

    @root_validator(pre=False)
    def save_settings(cls, values: Dict[str, Any]) -> Dict[str, Any]:
        print('SAVING!')
        print(values)
        def serialize_basemodel(model: BaseModel):
            if isinstance(model, BaseModel):
                return model.dict()
            else:
                raise TypeError(f'{type(model)} is not serializable!')

        with open('config.json', 'w', encoding='utf-8') as f:
            json.dump(values, f, ensure_ascii=False, indent=2,
                      default=serialize_basemodel)
        return values

    class Config:
        validate_assignment: bool = True


s = Settings()
print('Saving top level:')
s.foo = 'baz'
print('Saving bottom level:')
s.nested = {'test': 'bar'}
SAVING!
{'nested': NestedSettings(test='foobar'), 'foo': 'bar'}
Saving top level:
SAVING!
{'nested': NestedSettings(test='foobar'), 'foo': 'baz'}
Saving bottom level:
SAVING!
{'nested': NestedSettings(test='bar'), 'foo': 'baz'}