Embed models
Embed Models¶
Embed models allow you to use a DbmModel subclass as a field type in another model. The embedded model is stored inline within the parent model’s database record as a dictionary, rather than in a separate table.
This is useful when you want to group related fields together and reuse them across models while keeping type safety and validation.
Basic Usage¶
from pydbm import DbmModel
class Address(DbmModel):
street: str
city: str
class UserModel(DbmModel):
name: str
address: Address
You can pass an instance of the embedded model when creating the parent model:
address = Address(street="Main St", city="Istanbul")
user = UserModel(name="Hakan", address=address)
user.save()
You can also pass a dictionary, and it will be automatically converted to the embedded model:
user = UserModel(name="Hakan", address={"street": "Main St", "city": "Istanbul"})
user.save()
Accessing Embedded Fields¶
When you retrieve a model from the database, the embedded field is returned as a model instance:
loaded_user = UserModel.objects.get(id=user.id)
assert isinstance(loaded_user.address, Address)
assert loaded_user.address.street == "Main St"
assert loaded_user.address.city == "Istanbul"
Updating Embedded Fields¶
You can update the embedded field by passing a new model instance:
user = UserModel.objects.get(id=user.id)
new_address = Address(street="Second St", city="Ankara")
user.update(address=new_address)
Supported Field Types in Embed Models¶
Embed models support all the standard field types:
from pydbm import DbmModel
class Location(DbmModel):
name: str
lat: float
lng: float
active: bool
class Place(DbmModel):
title: str
location: Location
Using dict Instead of Embed Model¶
You can also use dict as a field type, but Pydbm will issue a warning recommending you use an embed model instead for better type safety:
from pydbm import DbmModel
# This works but will produce a warning
class UserModel(DbmModel):
name: str
metadata: dict
user = UserModel(name="Hakan", metadata={"role": "admin", "level": 5})
user.save()
loaded = UserModel.objects.get(id=user.id)
assert loaded.metadata == {"role": "admin", "level": 5}
When using dict, the values must be basic Python literals (str, int, float, bool, None) since they are serialized using str() and deserialized using ast.literal_eval().
With embed models, all supported field types are properly serialized and deserialized through the type system, which is why they are the recommended approach.