我們在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中。我希望找到一種方法,但一次只能解決一個問題!
聖F的這一工作。謝謝! @univerio – Rookie
謝謝你!這是一個有趣的答案,我正在努力將問題減少到這個空間。我寫了[另一個問題](http:// stackoverflow。com/questions/43823552 /聲明類 - 與類 - 類型之間的區別),作爲一個更普遍的問題/觀察。如果你能回答這個問題,那將是非常好的。既爲我,也爲其他讀者着想。看起來這個問題有興趣。再次感謝你的幫助! – Rookie