基于表库动态创建sqlAlchemy Metaclass
我们在ERP系统中有几个客户端。每个客户端都有自己的数据库。数据库在架构方面是相同的。基于表库动态创建sqlAlchemy Metaclass
不要问我为什么,但ERP数据库没有正式定义的PK,所以它不可能反映数据库......反而我们发现声明一个Metaclass和一个表声明,详述了PK和自动加载工程。举个例子:
class Customers(Base):
__table__ = Table('Customers', Base.metadata,
Column('UniqueNo', Integer, primary_key=True),
schema = 'databaseName.schema',
autoload = True
快速不上schema =
一部分。每个数据库的模式都是相同的,但模式的命名(以及数据库名称本身)是不同的。定义在元类的模式就是这样,使我们能够翻过查询数据库,能够
当创建的代码结构,要做到元类声明的最简单的方法是手动。每个数据库都有一个.py文件,并在每个文件中执行相同的Metaclass声明,仅更改模式,并向类名添加后缀以避免命名混淆。像这样:
client1.py
class Customers_1(Base):
__table__ = Table('Customers', Base.metadata,
Column('UniqueNo', Integer, primary_key=True),
schema = 'Dbclient1.client1Schema',
autoload = True
client2.py
class Customers_2(Base):
__table__ = Table('Customers', Base.metadata,
Column('UniqueNo', Integer, primary_key=True),
schema = 'Dbclient2.client2Schema',
autoload = True
这样做,这样的工作,但我们的希望是,我们可以通过动态创建减少代码量的元类仅基于一个ERPTables.py文件。例如:
ERPTables.py
class Customers(Base):
__table__ = Table('Customers', Base.metadata,
Column('UniqueNo', Integer, primary_key=True),
autoload = True
这使我们走上了Metaclasses这条陌生的领域。我已经到了能够动态创建元类声明的地步。但是:注册声明是我理解不足的地方。我来了这么远:
from sqlalchemy import Table
import ERPTables
import inspect
def iterate_ERPTables_Tables():
for table in inspect.getmembers(ERPTables):
if isinstance(table[1], Table) :
return table[0], table[1]
dbSchemas = {'_1': 'Dbclient1.client1Schema', '_2': 'Dbclient2.client2Schema'}
tables = [iterate_TableTest_Tables()]
for key in dbSchemas:
for table in tables:
cls = type(table[0] + key, (Base,), {'__tablename__': table[0], '__table__': table[1]})
break
此代码有效!唯一的问题是SA Metaclass命名为cls。因此break
。没有它,我们试图声明几个具有相同类名的元类。
我尝试了好几种方法来解决这个问题,喜欢尝试使用不熟悉的元类观点:
dbSchemas = {'_1': 'Dbclient1.client1Schema', '_2': 'Dbclient2.client2Schema'}
tables = [iterate_TableTest_Tables()]
for key in dbSchemas:
for table in tables:
type(table[0] + key, (Base,), {'__tablename__': table[0], '__table__': table[1]}).__new__
要完全成熟的破解工作变通:
dbSchemas = {'_1': 'Dbclient1.client1Schema', '_2': 'Dbclient2.client2Schema'}
tables = [iterate_TableTest_Tables()]
for key in dbSchemas:
for table in tables:
exec("%s = %s" % (table[0] + key, type(table[0] + key, (Base,), {'__tablename__': table[0], '__table__': table[1]})))
但是我所有的attemtps的已没有丝毫的意义,所以,在绳索的末端,我转向了SO,希望有人能告诉我如何解决这个问题! PS:如果有人想知道,我还没有解决如何将模式从dbSchemas
注入到Metaclass中。我希望找到一种方法,但一次只能解决一个问题!
如果你要导出的参考类,你可以将它们添加到globals()
:
globals()[table[0] + key] = type(...)
圣F的这一工作。谢谢! @univerio – Rookie
谢谢你!这是一个有趣的答案,我正在努力将问题减少到这个空间。我写了[另一个问题](http:// stackoverflow。com/questions/43823552 /声明类 - 与类 - 类型之间的区别),作为一个更普遍的问题/观察。如果你能回答这个问题,那将是非常好的。既为我,也为其他读者着想。看起来这个问题有兴趣。再次感谢你的帮助! – Rookie