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 = sess.query(Item).options(eagerload('keywords')).select() names = [k.keyword.name for k in l[0].keywords] self.assert_(names == ['blue','red']) if __name__ == "__main__": testbase.main()