gino icon indicating copy to clipboard operation
gino copied to clipboard

[WIP] Add pydantic model creation method to Gino Model

Open bubthegreat opened this issue 4 years ago • 4 comments

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

bubthegreat avatar May 31 '20 22:05 bubthegreat

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!

fantix avatar Jun 05 '20 04:06 fantix

Any updates/thoughts/concerns? Very actual thing

xnuinside avatar Oct 15 '20 21:10 xnuinside

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. :(

wwwjfy avatar Oct 18 '20 16:10 wwwjfy

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
    })

Mastermind-U avatar Feb 25 '21 11:02 Mastermind-U