Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add pydantic model creation method to Gino Model #688

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/gino/declarative.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import collections

from pydantic import create_model
import sqlalchemy as sa
from sqlalchemy.exc import InvalidRequestError

Expand Down Expand Up @@ -361,6 +362,65 @@ def _init_table(cls, sub_cls):
)
return rv

@classmethod
def get_pydantic_model(cls):
"""Return a pydantic model from the GINO model definition.

Will check for an __exclude__ property on the class to identify
class attributes that should be excluded from the pydantic model
generation.


Example:

class User(db.Model):
__tablename__ = 'users'

name = db.Column(db.String())
User =
PUser = User.get_pydantic_model()
indent=2
print(PUser.schema_json(indent=2))
{
"title": "User",
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string"
}
},
"required": [
"name"
]
}
"""

keys = [str(key) for key in cls.__dict__.keys()]
# Assumption that may not be valid, but don't look at ones with _ in them.
valid_keys = [key for key in keys if not key.startswith('_')]
Comment on lines +400 to +402
Copy link

@Mastermind-U Mastermind-U Feb 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better if you use cls.__table__.columns.keys() method here.


# Allow exclusions of model attributes from the pydantic model.
if hasattr(cls, '__excluded__'):
valid_keys = [key for key in valid_keys if key not in cls.__excluded__]

# This may be unique to GINO where the python type is on a column, but
# It would be easy enough to make a reference table for this rather than
# pulling it directly from the model column.
field_definitions = {}
for key in valid_keys:
col = getattr(cls, key)
col_type = col.type.python_type
# Don't forget ellipses after this, or pydantic won't create
# the schema and validators properly.
field_definitions[key] = (col.type.python_type,...)

# Create our pydantic model
pmodel = create_model(cls.__name__, **field_definitions)

return pmodel


def declarative_base(metadata, model_classes=(Model,), name="Model"):
"""Create a base GINO model class for declarative table definition.
Expand Down