如何使用Flask-SQLAlchemy创建可重用的组件?

时间:2011-04-25 07:03:00

标签: sqlalchemy code-reuse flask flask-sqlalchemy

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

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

2 个答案:

答案 0 :(得分:3)

首先,您必须共享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快捷方式。

抱歉我的英语不好。

答案 1 :(得分:1)

您应该使用flask.current_app,它是访问当前应用程序的代理对象,它是某些扩展中使用的代理对象。所以,你的代码看起来像这样:

from flask import current_app
from flaskext.sqlalchemy import SQLAlchemy

db = SQLAlchemy(current_app)

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