使用__bind_key__在多个相同数据库中继承Flask表类

2 投票
2 回答
2815 浏览
提问于 2025-04-16 22:30

我正在尝试建立一个管理控制面板,目的是把四个不同的电商网站整合在一起。这些网站的数据库结构是完全相同的(都是MySQL)。

出什么问题了?

无论我输入哪个订单ID和网站,都会出现404未找到的错误。无论我怎么组合,都无法找到任何记录。总是404错误,我也不知道为什么。所以我在这里求助。

代码

我尝试通过为每个表创建基础模型类来实现这个目标。然后根据不同的数据库,创建这些基础类的子类,使用不同的绑定键。这是代码的简要概述——如果你需要更多信息,请告诉我:

basemodels.py

MyOrderClass(db.Model):
    __tablename__ = 'messytablename'
    id = db.Column('order_id', db.Integer, primary_key=True)
    order_total = db.Column(db.Float)
    order_status = db.Column(db.String(1))

site2models.py

class Site2Order(MyOrderClass):
    __bind_key__ = 'site2'

__init__.py

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://user:pass@localhost/site'
app.config['SQLALCHEMY_BINDS'] = {
    'site1':'mysql://user:pass@localhost/site1',
    'site2':'mysql://user:pass@localhost/site2',
    'site3':'mysql://user:pass@localhost/site3',
    'site4':'mysql://user:pass@localhost/site4'
}

views.py

@app.route('/order/<site>/<orderid>')
def show_order(site, orderid):
    if site == 'site1':
        orderObject = Site1Order
    if site == 'site2':
        orderObject = Site2Order
    if site == 'site3':
        orderObject = Site3Order
    if site == 'site4':
        orderObject = Site4Order

    order = orderObject.query.get(orderid)
    return render_template('order.html', order=order)

原始网站是用PHP构建的,结构和命名规范都不太整洁。

感谢你的时间。

2 个回答

1

db.Model.metadata.tables['你的模型名称'].info['绑定键'] = '你的绑定名称'

我找到了一种简单的方法

3

现在关于SQLALCHEMY_BINDS的问题是,它只在像create_all()或drop_all()这样的操作中使用。你需要为这些操作更改会话绑定:

db.session.bind = db.get_engine(app, 'site2')

目前正在进行一些工作来改变这一点,但还没有正式发布。

你的代码可以像这样:

db.session.bind = db.get_engine(app, orderObject.__bind_key__)
order = orderObject.query.get(orderid)

但要记住,这会改变全局会话,并不会重置它。你需要自己去重置,或者写一个上下文管理器,这样你就可以使用with语句来处理。

如果你的模型在所有数据库中都是一样的,这也可以让你只用一个类来处理所有数据库,只需保留bind_key,然后用一个特殊的绑定会话对象来查询它们。

编辑:在Flask-SQLAlchemy 0.15版本中,如果你正确地定义了__bind_key__,那么对于不同的数据库,可以简单地使用MyModel.query.filter(...)。

撰写回答