odmantic
odmantic copied to clipboard
Handling references to external models by `id`
Hi,
I'm working on a FastAPI application with ODMantic and it's fantastic. However, I'm a bit confused by how references to external models are handled. Maybe I did it all wrong, but I came up with the same solution than https://github.com/art049/odmantic/issues/127#issuecomment-887339892 in order to avoid a validation error
Let's say that I'm trying to model a project and its builds:
class Build(Model):
project: Project = Reference()
name: str
date: datetime
success: bool
I must use an additional model:
class BuildInApi(Model):
project_id: str
name: str
date: datetime
success: bool
Or project_id: Optional[ObjectId]
but it's the same.
And then to:
- Find the related project.
- Map the fields between the two models
As in this example endpoint:
@router.put("/builds/", response_model=Build, tags=["builds"])
async def create_build(build_in_api: BuildInApi, request: Request):
project = await request.app.engine.find_one(Project, Project.id == ObjectId(build_in_api.project_id))
build = Build(project=project,
name=build_in_api.name,
date=build_in_api.date,
success=build_in_api.success,
payload=build_in_api.payload)
await request.app.engine.save(build)
return build
This is cumbersome and errorprone so I'm sure I am missing something.
Hello, thanks for showing this use case. Yeah, currently this is, unfortunately, the only way. Although you could avoid manual unpacking like this:
@router.put("/builds/", response_model=Build, tags=["builds"])
async def create_build(build_in_api: BuildInApi, request: Request):
project = await request.app.engine.find_one(Project, Project.id == ObjectId(build_in_api.project_id))
build = Build(project=project, **build_in_api.dict(exclude="project_id"))
await request.app.engine.save(build)
return build
However, it doesn't relieve the pain that much. I'll include this use case in the reference rework coming soon!