gino
gino copied to clipboard
[WIP] Add pydantic model creation method to Gino Model
Adds a class method 'get_pydantic_model' to the base Model class that introspects the class to provide a pydantic model.
Questions that still need answers/feedback:
- Do we have enough context on a model to follow relations without additional dependencies?
- Is this the right place for this method, or should it live somewhere else or in a new utility module?
- Is there a better way to introduce this to the classes, like with a consistent dunder method that we can utilize elsewhere, etc.
Things to do:
- Follow relations with a recursion limit
- Test more complex models
- Add lots of tests
Sorry, I was in a move in the last few days and everything is a bit messy. I Will take a look this weekend. Thanks for the PR!
Any updates/thoughts/concerns? Very actual thing
Sorry, I've been a bit busy lately at work. I guess it's similar situation for Fantix. Currently I'm limited to check issues but not PRs. I'll try my best to look into it, but also as this is WIP, likely this won't be merged into master soon. :(
Since the author still hasn't merged, and if someone's looking for the same feature, I've made a simple replacement, just copypaste it (note: there's python3.9 typing):
from typing import Optional, Type
from gino.declarative import Model
from pydantic import BaseModel, create_model
def gino_to_pydantic(
model: Type[Model],
*,
include: Optional[list[str]] = None,
exclude: Optional[list[str]] = None,
) -> Type[BaseModel]:
"""Convert model to pydantic class representation.
:param model: gino model
:type model: Type[Model]
:param include: fields to include, defaults to None,
if None, all fields are included
:type include: Optional[list[str]], optional
:param exclude: excludes fields form included, defaults to None
:type exclude: Optional[list[str]], optional
:return: pydantic model class with casted gino fields
:rtype: Type[BaseModel]
"""
if include is None:
include = model.__table__.columns.keys()
if exclude is not None:
include = [field for field in include if field not in exclude]
return create_model(model.__name__, **{ # type: ignore
str(column.name): (column.type.python_type, ...)
for column in model.__table__.columns if str(column.name) in include
})