Мне недавно пришлось использовать метакласс, чтобы помочь декларативно определить модель SQLAlchemy вокруг таблицы базы данных, заполненной данными переписи США от http://census.ire.org/data/bulkdata.html
IRE предоставляет оболочки базы данных для таблиц данных переписи, которые создают целочисленные столбцы в соответствии с соглашением об именах из Бюро переписей p012015, p012016, p012017 и т. Д.
Я хотел: а) иметь возможность доступа к этим столбцам с использованием синтаксиса model_instance.p012017
, б) быть достаточно явным в том, что я делал, и в) не нужно явно определять десятки полей в модели, поэтому я создал подкласс DeclarativeMeta
для перебора диапазона столбцов и автоматического создания полей модели, соответствующих столбцам:
from sqlalchemy.ext.declarative.api import DeclarativeMeta
class CensusTableMeta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
table = 'p012'
for i in range(1, 49):
fname = "%s%03d" % (table, i)
dict_[fname] = Column(Integer)
setattr(cls, fname, dict_[fname])
super(CensusTableMeta, cls).__init__(classname, bases, dict_)
Затем я могу использовать этот метакласс для определения модели и получить доступ к автоматически перечисляемым полям модели:
CensusTableBase = declarative_base(metaclass=CensusTableMeta)
class P12Tract(CensusTableBase):
__tablename__ = 'ire_p12'
geoid = Column(String(12), primary_key=True)
@property
def male_under_5(self):
return self.p012003
...