On Jul 7, 2010, at 3:19 PM, Nikolaj wrote: > Hi there, > > I'd like to create a column composite for amounts of money and their > currency. However, the difficulty comes in keeping the currencies in a > separate table and enabling my composite to find this relationship. > > Is there some way to set the Currency on my Money type implementation > automatically?
seems like your MoneyComposite is the point at which the currency is known and the Money is recieved. I think you'd want to instrument up MoneyComposite to intercept set events. > > Apologies for the amount of code here: > > from sqlalchemy import create_engine, Column, ForeignKey > from sqlalchemy.ext.declarative import declarative_base > from sqlalchemy.orm import scoped_session, sessionmaker, composite, > relationship, joinedload > from sqlalchemy.types import Integer, String, Numeric, TypeDecorator > > from decimal import Decimal > import warnings > > warnings.simplefilter('ignore') > > class MoneyComposite(object): > def __init__(self, amount, currency): > self.amount = amount > self.currency = currency > > # Set the currency on the Money type here > > def __composite_values__(self): > return (self.amount, self.currency) > > class MoneyType(TypeDecorator): > impl = Numeric > > def __init__(self, *args, **kwargs): > super(MoneyType, self).__init__(*args, precision=11, scale=2, > **kwargs) > > def process_bind_param(self, value, dialect): > if isinstance(value, Money): > value = value.value > return value > > def process_result_value(self, value, dialect): > return Money(value) > > class Money(object): > def __init__(self, value): > self.value = value > self.currency = Currency(symbol='USD', rate=Decimal('1.5')) > > def __str__(self): > return '%s %s' % (self.currency.symbol, self.value * > self.currency.rate) > > engine = create_engine('sqlite:///:memory:', echo=True) > Base = declarative_base(bind=engine) > Session = scoped_session(sessionmaker(bind=engine)) > > class Currency(Base): > __tablename__ = 'currencies' > symbol = Column(String, primary_key=True) > rate = Column(Numeric) > > class Item(Base): > __tablename__ = 'items' > id = Column(Integer, primary_key=True) > name = Column(String(50)) > > price = composite( > MoneyComposite, > Column('amount', MoneyType), > Column('currency', String, ForeignKey(Currency.symbol)) > ) > > currency = relationship(Currency) > > Base.metadata.create_all() > > c = Currency(symbol='USD', rate=Decimal('1.5')) > Session.add(c) > > price = MoneyComposite(Money('5'), c.symbol) > > i = Item(name='foobar', price=price) > Session.add(i) > > Session.commit() > > i = Session.query(Item).options(joinedload(Item.currency, > innerjoin=True)).first() > print i.price.amount > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to sqlalch...@googlegroups.com. > To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.