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?

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.

Reply via email to