I would like to allow some of the CompositeProperty columns I'm building to get their names dynamically, in a manner that mirrors how columns get their names in sqlalchemy's declarative mapper. The best way I found to implement this behavior is to do the following:
class DeferredCompositeProperty(CompositeProperty):
def get_column_names(self, key):
raise NotImplementedError
def undefer_column_names(self, key):
for col, name in zip(self.columns, self.get_column_names(key)):
col.key = name
class CustomDeclarativeMeta(DeclarativeMeta):
def __new__(cls, name, bases, d):
def undefer(k, v):
if isinstance(v, DeferredCompositeProperty):
v.undefer_column_names(k)
for k, v in d.iteritems():
undefer(k, v)
for base in bases:
for k, v in base.__dict__.iteritems():
undefer(k, v)
return DeclarativeMeta.__new__(cls, name, bases, d)
class MoneyComposite(DeferredCompositeProperty):
def __init__(self):
DeferredCompositeProperty.__init__(self, <SomeCompositeClass>, Column(Integer), Column(String))
def get_column_names(self, key):
return [
'{}_amount'.format(key),
‘{}_currency’.format(key)
]
Base = declarative_base(metaclass=CustomDeclarativeMeta)
class ExampleModel(Base):
funds = MoneyComposite()
This would result in ExampleModel having the columns: funds_amount and funds_currency automatically without having to specify them directly.
Am I doing this right or is there a better way?