How to dynamically generate marshmallow schemas for SQLAlchemy models

I am creating a Flask API using SQLAlchemy models. I do not want to define a circuit for each model that I have, I do not want to do this every time:

class EntrySchema(ma.ModelSchema):
    class Meta:
        model = Entry

I would like every model to have a circuit, so it can easily reset itself. Creating the default schema and installing Schema.Meta.model did not work:

class Entry(db.Model):
    __tablename__ = 'entries'

    id = db.Column(db.Integer, primary_key=True)
    started_at = db.Column(db.DateTime)
    ended_at = db.Column(db.DateTime)
    description = db.Column(db.Text())

    def __init__(self, data):
        for key in data:
            setattr(self, key, data[key])

        self.Schema = Schema
        self.Schema.Meta.model = self.__class__

    def dump(self):
        schema = self.Schema()
        result = schema.dump(self)
        return result


class Schema(ma.ModelSchema):
    class Meta:
        pass

Why is the general model replacement scheme different from the declared model?

+7
source share
3 answers

You can create a class decorator that will add Schemato your models:

def add_schema(cls):
    class Schema(ma.ModelSchema):
        class Meta:
            model = cls
    cls.Schema = Schema
    return cls

and then

@add_schema
class Entry(db.Model):
    ...

The schema will be available as an attribute of the class Entry.Schema.

, , , Schema , , , . , .

Python, . , .

+5

. :

# myproject/schemas.py

from marshmallow_sqlalchemy import ModelSchema

from .db import Session

class BaseSchema(ModelSchema):
    class Meta:
        sqla_session = Session

:

# myproject/users/schemas.py

from ..schemas import BaseSchema
from .models import User

class UserSchema(BaseSchema):

    # Inherit BaseSchema options
    class Meta(BaseSchema.Meta):
        model = User

, /

0

-sqlalchemy:

" SQLAlchemy. , , . SQLAlchemy , , SQLAlchemy ".

flask_sqlalchemy & marshmallow_sqlalchemy:

from flask_sqlalchemy import SQLAlchemy
from marshmallow_sqlalchemy import ModelConversionError, ModelSchema
from sqlalchemy import event
from sqlalchemy.orm import mapper


db = SQLAlchemy()


def setup_schema(Base, session):
    # Create a function which incorporates the Base and session information
    def setup_schema_fn():
        for class_ in Base._decl_class_registry.values():
            if hasattr(class_, "__tablename__"):
                if class_.__name__.endswith("Schema"):
                    raise ModelConversionError(
                        "For safety, setup_schema can not be used when a"
                        "Model class ends with 'Schema'"
                    )

                class Meta(object):
                    model = class_
                    sqla_session = session

                schema_class_name = "%sSchema" % class_.__name__

                schema_class = type(schema_class_name, (ModelSchema,), {"Meta": Meta})

                setattr(class_, "Schema", schema_class)

    return setup_schema_fn


event.listen(mapper, "after_configured", setup_schema(db.Model, db.session))

:

https://marshmallow-sqlalchemy.readthedocs.io/en/latest/recipes.html#automatically-generating-schemas-for-sqlalchemy-models

0

Source: https://habr.com/ru/post/1672685/


All Articles