将“外部”类模型与flask sqlalchemy相关联

melchoir55

我们将中央类模型用于各种python模块。该模型是使用SQLAlchemy定义的。这些类都继承自declarative_base。

例如,我们的模型定义如下所示:

Base = declarative_base()

class Post(Base):
    __tablename__ = 'Posts'
    id = Column(INT, primary_key=True, autoincrement=True)
    body = Column(TEXT)
    timestamp = Column(TIMESTAMP)
    user_id = Column(INT, ForeignKey('Users.uid'))

我们一直在构建一个Flask Web应用程序,其中我们采用了相同的模型。我们发现了一个棘手的问题,因为flask-sqlalchemy的设计方式似乎希望通过传递会话的活动实例来定义其模型中使用的所有类。这是“适当的” flask-sqalchemy类模型定义的示例:

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

请注意,上面的flask-sqlalchemy示例需要一个已经实例化的sql会话。这让我们感到恐惧,因为我们完全不知道如何将SqlAlchemy模型集成到烧瓶中。我们真的特别想使用flask-security套件。

SO之前已经提过这个问题。例如,在这里:如何在现有的sqlalchemy模型中使用flask-sqlalchemy?

我们的要求与接受答复的人的要求不同。响应指出,人们失去了使用User.query的能力,但这恰恰是我们必须保留的东西之一。

放弃我们漂亮,优雅,中央类的模型定义,而转向flask-sqlalchemy似乎需要什么是不可行的。有什么方法可以将模型与SQLAlchemy()对象关联?在类上获得.query()方法的加分点似乎是flask-security所需的。

melchoir55

解决方案:

到目前为止,执行此操作的最佳方法如下:

实施或导入sqlalchemy base

from sqlalchemy.ext.declarative import declarative_base

base = declarative_base()


class Base(base):

    __abstract__ = True
    uid = Column(Integer, primary_key=True, autoincrement=True)

注册外部基础:

from flask_sqlalchemy import SQLAlchemy
from model.base import Base

app = Flask(__name__)
db = SQLAlchemy(app, model_class=Base)

为后代存档:

我花了很多时间来寻找答案。今天,这比我最初提出这个问题时要容易得多,但是它仍然不是很简单。

对于任何决定自己进行安全性保护的人,我建议对使用flask的常见设计模式进行以下出色的阐述,但这些模式避免使用flask-security之类的不必要依赖项:https : //exploreflask.com/users.html

更新:对于任何有兴趣的人,与之相关的补丁已经有一段时间了。到目前为止,它仍未发布,但是您可以在此处查看其进度:https : //github.com/mitsuhiko/flask-sqlalchemy/pull/250#issuecomment-77504337

更新:我从上述补丁中获取了代码,并为SQLAlchemy对象创建了本地替代,该替代允许一个人注册一个外部基础。我认为这是直到FSA正式添加此功能之前的最佳选择。这是该类中有兴趣的人的代码。已测试使用Flask-SqlAlchemy 2.2

在register_external_base中打补丁:

import flask_sqlalchemy
'''Created by Isaac Martin 2017. Licensed insofar as it can be according to the standard terms of the MIT license: https://en.wikipedia.org/wiki/MIT_License. The author accepts no liability for consequences resulting from the use of this software. '''
class SQLAlchemy(flask_sqlalchemy.SQLAlchemy):
    def __init__(self, app=None, use_native_unicode=True, session_options=None,
                 metadata=None, query_class=flask_sqlalchemy.BaseQuery, model_class=flask_sqlalchemy.Model):

        self.use_native_unicode = use_native_unicode
        self.Query = query_class
        self.session = self.create_scoped_session(session_options)
        self.Model = self.make_declarative_base(model_class, metadata)
        self._engine_lock = flask_sqlalchemy.Lock()
        self.app = app
        flask_sqlalchemy._include_sqlalchemy(self, query_class)
        self.external_bases = []

        if app is not None:
            self.init_app(app)

    def get_tables_for_bind(self, bind=None):
        """Returns a list of all tables relevant for a bind."""
        result = []
        for Base in self.bases:
            for table in flask_sqlalchemy.itervalues(Base.metadata.tables):
                if table.info.get('bind_key') == bind:
                    result.append(table)

        return result

    def get_binds(self, app=None):
        """Returns a dictionary with a table->engine mapping.
        This is suitable for use of sessionmaker(binds=db.get_binds(app)).
        """
        app = self.get_app(app)
        binds = [None] + list(app.config.get('SQLALCHEMY_BINDS') or ())
        retval = {}
        for bind in binds:
            engine = self.get_engine(app, bind)
            tables = self.get_tables_for_bind(bind)
            retval.update(dict((table, engine) for table in tables))
        return retval

    @property
    def bases(self):
        return [self.Model] + self.external_bases

    def register_base(self, Base):
        """Register an external raw SQLAlchemy declarative base.
        Allows usage of the base with our session management and
        adds convenience query property using self.Query by default."""

        self.external_bases.append(Base)
        for c in Base._decl_class_registry.values():
            if isinstance(c, type):
                if not hasattr(c, 'query') and not hasattr(c, 'query_class'):
                    c.query_class = self.Query
                if not hasattr(c, 'query'):
                    c.query = flask_sqlalchemy._QueryProperty(self)

                    # for name in dir(c):
                    #     attr = getattr(c, name)
                    #     if type(attr) == orm.attributes.InstrumentedAttribute:
                    #         if hasattr(attr.prop, 'query_class'):
                    #             attr.prop.query_class = self.Query

                    # if hasattr(c , 'rel_dynamic'):
                    #     c.rel_dynamic.prop.query_class = self.Query

用法如下:

app = Flask(__name__)
db = SQLAlchemy(app)
db.register_base(base)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

将App与Epub格式相关联

来自分类Dev

将玩家ID与交易相关联?

来自分类Dev

将修订与Redmine问题相关联

来自分类Dev

将Braintree PaymentMethod与地址相关联

来自分类Dev

将NServiceBus Saga与ConversationId相关联

来自分类Dev

将按钮与Enter键相关联

来自分类Dev

CakePhp将评论与帖子相关联

来自分类Dev

将信息框与图像相关联

来自分类Dev

将玩家ID与交易相关联?

来自分类Dev

将组合的索引与值相关联

来自分类Dev

将特定索引与向量相关联

来自分类Dev

Firebase - 将图片与用户相关联?

来自分类Dev

SceneKit:将节点与模型对象相关联

来自分类Dev

将Python / Django模型对象与用户相关联

来自分类Dev

如何将ActiveRecord模型和普通类模型相关联

来自分类Dev

将屏幕与kivy中的GridLayout类相关联

来自分类Dev

将屏幕与kivy中的GridLayout类相关联

来自分类Dev

SequelizeEagerLoadingError'模型1'未与'模型2'相关联

来自分类Dev

如果关系使用“as”,则属性不与模型相关联

来自分类Dev

将用户控件与ViewModel类相关联

来自分类Dev

在Haskell中将非类型类函数与类型相关联

来自分类Dev

将运算结果与哈希图值相关联

来自分类Dev

将aiohttp请求与其响应相关联

来自分类Dev

将javascript对象与SVG元素相关联

来自分类Dev

将文件类型与Chrome打包应用相关联

来自分类Dev

Laravel-5,将角色与用户相关联

来自分类Dev

我正在尝试将C ++引用与指针相关联

来自分类Dev

如何将github问题与分支相关联?

来自分类Dev

在WPF中,什么将ListBoxItem与ListBox相关联?