I'm currently trying to automatically save a pydantic.BaseSettings-object to a json-file on change. The model is loaded out of the json-File beforehand. A minimal working example of the saving procedure is as follows:
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'
The output generated is:
SAVING!
Saving top level:
SAVING!
Saving bottom level:
I'd like to let the object save even after assigning the bottom level s.nested.bar. Is there any way to achieve this?
Thanks in advance for any hints!
My answer isn't elegant, but since the validate_assignment seems to only check the the root fields you can still take advantage of the of the action by changing
s.nested.test
to
s.nested = {'test': 'bar'}
and it will work. Here is the example code and output for better demonstration.
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'}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With