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.

Reply via email to