【问题标题】:How do you make a re-usable component with Flask-SQLAlchemy?如何使用 Flask-SQLAlchemy 制作可重用的组件?
【发布时间】:2011-08-12 04:13:05
【问题描述】:

假设我有我的 Flask 应用程序的一部分,我想将其取出并用于多个不同的项目。它具有使用 Flask-SQLAlchemy 的 SQLAlchemy 模型,以及视图和模板。我可以使用模块获取 app.route 装饰器,但是如何处理 SQLAlchemy db 对象?

由于我的组件需要分开,我不能只导入 db 对象。但我认为我不应该两次创建 db 对象。我如何将其元数据与项目其余部分的元数据混合在一起?

【问题讨论】:

    标签: sqlalchemy code-reuse flask flask-sqlalchemy


    【解决方案1】:

    首先,您必须共享metadata,并且不要使用flask-sqlalchemy db.Model 作为可重用应用程序的基础。

    其次,您必须重新创建所有类,并从 flask-sqlalchemy 扩展它们的新基础,以支持信号、快捷方式和其他内容。

    整合基地(可能有问题):

    def integrate_models(cls, nbase):
            new_bases = list(cls.__bases__) + [nbase]
            new_dict = dict(cls.__dict__)
            new_dict.update(dict(nbase.__dict__))
            return type.__new__(cls.__class__, cls.__name__, tuple(new_bases), new_dict)
    

    带有 sqlalchemy 扩展的示例 Flask 应用:

    # -*- coding: utf-8 -*-
    from flask import Flask
    from flaskext.sqlalchemy import SQLAlchemy
    
    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)
    
        def __init__(self, username, email):
            self.username = username
            self.email = email
    
        def __repr__(self):
            return '<User %r>' % self.username
    
    if __name__ == '__main__':
            from some_model_base import init_metadata
            init_metadata(db.Model.metadata)
    
            from some_model import SomeClass
    
            SomeClass = integrate_models(SomeClass, db.Model)
    
            db.create_all()
    
            print SomeClass.query.all()
    

    其中 some_model_base.py:

    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base()
    
    def init_metadata(metadata):
        Base.metadata = metadata
    

    还有 some_model.py:

    from sqlalchemy import Column, Integer, String
    from some_model_base import Base
    
    class SomeClass(Base):
        __tablename__ = 'some_table'
        id = Column(Integer, primary_key=True)
        name =  Column(String(50))
    

    在这个例子中只测试了 db.create_all 和 SomeClass.query 快捷方式。

    对不起,我的英语不好。

    【讨论】:

    • 嗯,我需要试试这个。你能找到一种方法来配置其他模块中的模型与主程序中的模型有关系吗?
    • 我认为最好的方法是在您的可重用应用程序基类或 MixIn 中声明,然后构建子类化它们的具体模型。
    【解决方案2】:

    你应该使用flask.current_app,它是一个访问当前应用程序的代理对象,它是在一些扩展中使用的。因此,您的代码将如下所示:

    from flask import current_app
    from flaskext.sqlalchemy import SQLAlchemy
    
    db = SQLAlchemy(current_app)
    

    然后像往常一样使用db 对象。但是我不确定如果用户使用了您的模块并且还需要使用flaskext.sqlalchemy,这是否可行,也许它会发生冲突,我建议对此进行测试,以确保您的模块与任何模块 100% 兼容flask 申请。

    【讨论】:

      猜你喜欢
      • 2018-05-14
      • 2014-10-05
      • 1970-01-01
      • 2022-07-14
      • 2021-09-26
      • 2022-09-28
      • 1970-01-01
      • 2020-06-30
      • 1970-01-01
      相关资源
      最近更新 更多