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 [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> 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 [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.