How to fix my approach to use the same models in vanilla SQLAlchemy and Flask-SQLAlchemy?

后端 未结 1 1396
没有蜡笔的小新
没有蜡笔的小新 2020-12-21 11:14

I came across several approaches on how to use the vanilla SQLAlchemy models in Flask-SQLAlchemy.

It works like a charm to use models that inherit from Base

相关标签:
1条回答
  • 2020-12-21 12:08

    I found a good solution inspired by a Factory pattern and Declarative Mixins as mentioned in the SQLAlchemy docs.

    For complex multi-level inheritance scenarios a different approach is needed, using @declared_attr.cascading.

    
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy import Column, Integer, String
    from sqlalchemy import MetaData
    
    from sqlalchemy.ext.declarative import declarative_base
    from flask_sqlalchemy import SQLAlchemy
    
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + '/tmp/test_app.db'
    engine = create_engine(SQLALCHEMY_DATABASE_URI, echo=True)
    
    # for vanilla
    Base = declarative_base()
    
    # for Flask (import from app once initialized)
    db = SQLAlchemy()
    
    
    class MachineMixin:
    
        __tablename__ = 'machine'
        id = Column(Integer, primary_key=True)
        name = Column(String(100))
        status = Column(Integer)
    
    
    class ModelFactory:
    
        @staticmethod
        def create(which_model, which_parent):
    
            if which_parent == 'flask_sqlalchemy':
    
                parent = db.Model
    
            elif which_parent == 'pure_sqlalchemy':
    
                parent = Base
    
            # now use type() to interit, fill __dict__ and assign a name
            obj = type(which_model.__name__ + '_' + which_parent,
                        (which_model, parent),
                        {})
            return obj
    
    
    test_scenario = 'pure_sqlalchemy' # 'flask_sqlalchemy'
    
    Machine = ModelFactory.create(MachineMixin, test_scenario)
    
    if test_scenario == 'flask_sqlalchemy':
    
        db.metadata.drop_all(bind=engine)
        db.metadata.create_all(bind=engine)
    
    elif test_scenario == 'pure_sqlalchemy':
    
        Base.metadata.drop_all(bind=engine)
        Base.metadata.create_all(bind=engine)
    
    
    Session = sessionmaker(bind=engine)
    session = Session()
    session.add(Machine(name='Bob', status=1))
    session.commit()
    
    
    0 讨论(0)
提交回复
热议问题