Hi!

I have a model with a many-to-many relation, similar to the 
Broker/Holding/Stocks example in the docs. I've set up relationships between 
both sides using the association object pattern. Finally, I've set up the 
collection class of those relationships to an 
attribute_mapped_collection. It is expected that when an instance of Holding 
is created, it should appear on BOTH attribute_mapped_collections, but the 
KEY is only present on one of them.

Following there is a small adaptation of the Broker/Stocks/Holding model to 
explain the problem.

from sqlalchemy import Column, ForeignKey, MetaData, Table
from sqlalchemy import Integer, String, Numeric
from sqlalchemy.orm import mapper, relationship
from sqlalchemy.orm.collections import attribute_mapped_collection
meta = MetaData()
stocks_table = Table("stocks", meta,
   Column('symbol', String(10), primary_key=True),
   Column('last_price', Numeric)
)
brokers_table = Table("brokers", meta,
   Column('id', Integer,primary_key=True),
   Column('name', String(100), nullable=False)
)
holdings_table = Table("holdings", meta,
  Column('broker_id', Integer, ForeignKey('brokers.id'), primary_key=True),
  Column('symbol', String(10), ForeignKey('stocks.symbol'), 
primary_key=True),
  Column('shares', Integer)
)
class Broker(object):
    def __init__(self, name):
        self.name = name
class Stock(object):
    def __init__(self, symbol):
        self.symbol = symbol
        self.last_price = 0
class Holding(object):
    def __init__(self, broker=None, stock=None, shares=0):
        self.broker = broker
        self.stock = stock
        self.shares = shares
mapper(Stock, stocks_table, properties={
    'by_broker': relationship(Holding, back_populates="stock",
        collection_class=attribute_mapped_collection('broker'))
})
mapper(Broker, brokers_table, properties={
    'by_stock': relationship(Holding, back_populates="broker",
        collection_class=attribute_mapped_collection('stock'))
})
mapper(Holding, holdings_table, properties={
    'stock': relationship(Stock, back_populates="by_broker"),
    'broker': relationship(Broker, back_populates="by_stock")
})
broker = Broker('paj')
stock  = Stock('ZZK')
holding = Holding(broker, stock, 10)
print stock.by_broker
print broker.by_stock

The expected behaviour would be:

{<__main__.Broker object at 0xefce10>: <__main__.Holding object at 
0xf00910>}
{<__main__.Stock object at 0x1c74190>: <__main__.Holding object at 
0xf00910>}


But I get:

{<__main__.Broker object at 0xefce10>: <__main__.Holding object at 
0xf00910>}
{*None*: <__main__.Holding object at 0xf00910>}

Debugging in the code of sqlalchemy I assume the problem is that the 
addition of the Holding instance in the attribute_mapped_collections is done 
in two steps. During Holding object creation, when the first attribute 
(broker) is set, it fires an event and causes its addition to the 
broker.by_stock collection, but as stock is still not set, the key is None. 
Then, when the second attribute (stock) is set, it get correctly added to 
the collection as broker value is already set.

Does sqlalchemy support any other way of achieving the correct behaviour? Is 
this a bug? Should I file a report?

Thank you in advance!

Pau.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/kGTIEgoMnJIJ.
To post to this group, send email to sqlalchemy@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