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 [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.