在多个Oracle模式之间共享的Flask SQLAlchemy模型

时间:2019-12-20 14:55:04

标签: python oracle flask sqlalchemy schema

我必须创建一个Flask应用程序,该应用程序需要从放置在同一Oracle实例上的多个几乎相同的模式中读取数据。我只能由“ read_only”用户连接到此数据库。 通过这样做,我正在使用蓝图。

project
|-warehouse01
|   -__init__.py 
|   - view.py
|-warehouse02
|   -__init__.py 
|   - view.py
|-warehouse999
|   -__init__.py 
|   - view.py
-model.py
run.py
config.py 

当然所有模式的模型都是相同的

class Product(db.Model):
    #__table_args__ = {'schema': 'warehouse01'}
    __tablename__ = 'PRODUCTS'
    prod_no = db.Column(db.Integer, primary_key=True, nullable=False)
    prod_name = db.Column(db.String(35), nullable=False)
    quantity = db.Column(db.Integer, nullable=False)
    ...
    steps = db.relationship('Shipment', backref='shipments', lazy='dynamic')

class Shipment(db.Model):
    __tablename__ = 'SHIPMENTS'
    #__table_args__ = {'schema': 'warehouse01'}
    shipm_no = db.Column(db.Integer,  ,  primary_key=True, nullable=False)
    prod_no = db.Column(db.Integer, db.ForeignKey('PRODUCTS.prod_no'), nullable=False)
    customer_id= db.Column(db.Integer, db.ForeignKey('CUSTOMERS.customer_id') nullable=False)
    ...


问题是通过不同的架构进行连接(READ_ONLY),我必须在 table_args 中声明一个架构 我想对所有模式使用相同的模型。显然,我不想为所有蓝图创建单独的模型。 是否可以对所有模式使用相同的模型,或者可以在蓝图中重新定义模式名称?

2 个答案:

答案 0 :(得分:0)

我认为您可以使用工厂函数即时创建模型:

def create_product_model(schema):
    class Product(db.Model):
        __table_args__ = {'schema': schema}
        __tablename__ = 'PRODUCTS'
        prod_no = db.Column(db.Integer, primary_key=True, nullable=False)
        prod_name = db.Column(db.String(35), nullable=False)
        quantity = db.Column(db.Integer, nullable=False)
        ...
        steps = db.relationship('Shipment', backref='shipments', lazy='dynamic')

    return Product

答案 1 :(得分:0)

最后,我找到了一种方法。不幸的是,@ Laurent LAPORTE提出的方法是不合适的。仅当我在模型中只有一个类时,并且仅在添加'extend_existing': True之后,它才起作用。如果我错了,请纠正我,但是在Flask中,在应用程序启动时声明了数据库模型。由于架构名称是__table_args__ = {'schema': schema}中声明的类的一部分,因此,当您想更改架构时,SqlAlchemy将其视为尝试使用模型注册表中的现有名称定义新类。

我的解决方案是从 table_args 中删除架构,并通过如下所示的sql命令设置架构名称: def estimate_schema(schema): db.engine.execute(f"alter session set current_schema={schema}")

这是我在每条路线之前使用的方法,并且有效

def index(): estimate_schema('warehouse01') ...