Greetings list,
I've trying to order a property which is a many-to-many relationship with
an association object, with columns that belong not to the relationship
table but to the associated one.
I think it's better to explain with an example, using the tables of the docs:
items = Table('items', metadata,
Column('item_id', Integer, primary_key=True),
Column('name', String(40)),
)
item_keywords = Table('item_keywords', metadata,
Column('item_id', Integer, ForeignKey('items.item_id')),
Column('keyword_id', Integer, ForeignKey('keywords.keyword_id')),
Column('data', String(40))
)
keywords = Table('keywords', metadata,
Column('keyword_id', Integer, primary_key=True),
Column('name', String(40))
)
And the problem lies in the Item mapper:
mapper(Item, items, properties={
'keywords' : relation(KeywordAssociation, association=Keyword,
order_by=[keywords.c.name], lazy=True)
})
So, given an item object (let's call it item), the idea is that item.keywords
be a ordered list not by item_keywords primary key but by keywords.name. But
this doesn't occur with lazy=False and even the mapper generates an exception
when lazy=True (exception saying that it doesn't find the 'name' column).
¿Is this an error or am I doing something wrong?
Anyway, thanks a lot to Michael for this remarkable piece of software, and for
the fabulous support he gives :)
Attached is a small but complete unit-test which exercises this problem.
Kind regards,
Raul Garcia.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sqlalchemy
-~--~~~~--~~--~--~---
import testbase
from sqlalchemy import *
class AssociationTest(testbase.PersistTest):
def setUpAll(self):
global items, item_keywords, keywords, metadata, Item, Keyword,
KeywordAssociation
metadata = BoundMetaData(testbase.db)
items = Table('items', metadata,
Column('item_id', Integer, primary_key=True),
Column('name', String(40)),
)
item_keywords = Table('item_keywords', metadata,
Column('item_id', Integer, ForeignKey('items.item_id')),
Column('keyword_id', Integer, ForeignKey('keywords.keyword_id')),
Column('data', String(40))
)
keywords = Table('keywords', metadata,
Column('keyword_id', Integer, primary_key=True),
Column('name', String(40))
)
metadata.create_all()
class Item(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return Item id=%d name=%s keywordassoc=%s % (self.item_id,
self.name, repr(self.keywords))
class Keyword(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return Keyword id=%d name=%s % (self.keyword_id, self.name)
class KeywordAssociation(object):
def __init__(self, keyword, data):
self.keyword = keyword
self.data = data
def __repr__(self):
return KeywordAssociation itemid=%d keyword=%s data=%s %
(self.item_id, repr(self.keyword), self.data)
mapper(Keyword, keywords)
mapper(KeywordAssociation, item_keywords, properties={
'keyword':relation(Keyword, lazy=False)
}, primary_key=[item_keywords.c.item_id, item_keywords.c.keyword_id],
order_by=[item_keywords.c.data])
mapper(Item, items, properties={
'keywords' : relation(KeywordAssociation, association=Keyword,
order_by=[keywords.c.name], lazy=True)
})
def tearDown(self):
for t in metadata.table_iterator(reverse=True):
t.delete().execute()
def tearDownAll(self):
clear_mappers()
metadata.drop_all()
def testassoc_orderby_lazy(self):
sess = create_session()
item1 = Item('item1')
item1.keywords.append(KeywordAssociation(Keyword('red'), 'red_assoc'))
item1.keywords.append(KeywordAssociation(Keyword('blue'), 'blue_assoc'))
sess.save(item1)
sess.flush()
l = sess.query(Item).select()
names = [k.keyword.name for k in l[0].keywords]
self.assert_(names == ['blue','red'])
def testassoc_orderby_eager(self):
sess = create_session()
item1 = Item('item1')
item1.keywords.append(KeywordAssociation(Keyword('red'), 'red_assoc'))
item1.keywords.append(KeywordAssociation(Keyword('blue'), 'blue_assoc'))
sess.save(item1)
sess.flush()
l =