我必须创建一个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 中声明一个架构 我想对所有模式使用相同的模型。显然,我不想为所有蓝图创建单独的模型。 是否可以对所有模式使用相同的模型,或者可以在蓝图中重新定义模式名称?
答案 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')
...