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

发布于 2024-11-27 10:50:30 字数 1526 浏览 0 评论 0原文

我正在尝试构建一个管理控制面板,将 4 个不同的电子商务网站整合在一起。这些站点都具有相同的数据库结构(均为 MySQL)。

出了什么问题?

我在输入的任何订单 ID 和网站上都收到 404 Not Found。无论我如何混合,我都无法获得任何记录。总是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 构建的,结构和命名约定不太整齐。

谢谢您的宝贵时间。

I'm trying to build an admin control panel that brings together 4 different ecommerce sites. The sites all have identical database structures (all MySQL).

What's Going Wrong?

I get 404 Not Found on any order ID and site I put in. No matter how I mix it I can not get any record to come up. Always a 404 and I have no idea why. SO here I am.

Code

I tried to do this by creating base model classes of every table. Then creating inherited clases of those base classes with a different bind key dependent on the DB it is meant for. This is a summarised view of the code - if you'd need anymore than this let me know:

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)

The original sites are built in PHP and have less than tidy structures and naming conventions.

Thank you for your time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

演出会有结束 2024-12-04 10:50:30

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(...) 。

The problem currently with SQLALCHEMY_BINDS is that it is only used for operations like create_all() or drop_all() - you need to change the session binding for that:

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

There's work ongoing to change that but it's not in the trunk yet.

Your code could be like:

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

But remember that this changes the global session and does not reset it, you'd need to do that yourself or write a contextmanager so that you can use the with statement for that.

If your models are identical over all databases this could also be the way to only have one class for all databases, leave the bind_key and query them with a special bind session object.

Edit: with the Flask-SQLAlchemy 0.15 Release a simple MyModel.query.filter(...) is possible for different databases if you defined __bind_key__ properly.

彩虹直至黑白 2024-12-04 10:50:30

db.Model.metadata.tables['你的模型名称'].info['bind_key'] = '你的bind_name'

我找到了一种让事情变得简单的方法

db.Model.metadata.tables['your model name'].info['bind_key'] = 'your bind_name'

I found a way to make things easy

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文