我们在ERP系统中有几个客户。每个客户端都有自己的数据库。数据库在架构方面是相同的。
不要问我为什么,但是ERP数据库没有正式定义的PK,因此无法反映数据库......我们发现声明一个Metaclass,带有表声明,详细说明了PK,和自动加载工作。一个例子:
class Customers(Base):
__table__ = Table('Customers', Base.metadata,
Column('UniqueNo', Integer, primary_key=True),
schema = 'databaseName.schema',
autoload = True
快速不在schema =
部分。每个数据库的模式都相同,但模式的命名(以及数据库名称本身)是不同的。像这样在Metaclass中定义模式,使我们能够在数据库中进行查询,能够
创建代码结构时,最简单的方法是手动执行Metaclass声明。为每个数据库提供一个.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文件动态创建Metaclasses来减少代码量。例如:
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的问题。我希望找到一种方法,但一次只有一个问题!
答案 0 :(得分:1)
如果要导出类的引用,可以将它们添加到globals()
:
globals()[table[0] + key] = type(...)