beanie
beanie copied to clipboard
The Document Model Is Corrupted After Saving Changes When a Nested `BaseModel` Is Used in a Dictionary
Hi,
First of all, thanks for publishing beanie as an open-source. I think it is awesome!
I am using the latest version of beanie (currently 1.11.0) on both Python 3.9 and Python 3.10.
I encountered a weird problem:
- Define a document that contains a nested model in a dictionary.
- Create an instance of the document.
- Save the document.
- Try to access the nested model in the saved document, and you get an error.
I managed to reproduce this issue in a standalone manner. Please see the below code for reproduction and the temporary workaround I am currently using.
import asyncio
from beanie import Document, init_beanie
from motor.motor_asyncio import AsyncIOMotorClient
from pydantic import BaseModel
CONNECTION_URI = "XXX_CONNECTION_URI_XXX"
DATABASE = "database"
class Book(BaseModel):
name: str
class Library(Document):
books: dict[str, Book]
async def main():
client = AsyncIOMotorClient(CONNECTION_URI)
database = client[DATABASE]
await init_beanie(database, document_models=[Library])
library = Library(
books={
"book": Book(name="my book")
}
)
print(library.books["book"].__class__) # <class '__main__.Book'>
print(library.books["book"].name) # my book
await library.create() # this call "corrupts" the document model
print(library.books["book"].__class__) # <class 'dict'>
try:
print(library.books["book"].name) # AttributeError: 'dict' object has no attribute 'name'
except AttributeError as err:
print(f"AttributeError: {err}")
# Workaround - make a fresh copy of the document with Pydantic
library_copy = Library.parse_obj(library.dict())
print(library_copy.books["book"].__class__) # <class '__main__.Book'>
print(library_copy.books["book"].name) # my book
if __name__ == "__main__":
asyncio.run(main())
Am I doing anything wrong, or using anything that is not meant to be supported? Or is this indeed a bug?