[sqlalchemy] Using order_by in an association many-to-many relationship with columns from the association object

2009-03-10 Thread Scott

Is there a way with the current iteration of SQLAlchemy to add a
column to the association table in a many-to-many relationship with
that column used to order the join? I looked at the order_by attribute
of the ManyToMany() relationship definition, but it seems that this is
expecting a string naming the column in the related entity. I'm using
Elixir on top of alchemy, but here are my relevant class and table
definitions:

procedure_cpt_codes = Table('procedure_cpt_codes', metadata,
autoload=True)

class CptCode(Entity):
using_options(tablename='cpt_codes', autosetup=True)

name = Field(Unicode)
code = Field(Unicode)
description= Field(Unicode)

class Procedure(Entity):
using_options(tablename='procedures', autosetup=True)

complications = OneToMany('Complication')
cpt_codes = ManyToMany(
'CptCode',
table = procedure_cpt_codes, lazy=False,
foreign_keys = lambda: [ procedure_cpt_codes.c.procedure_id,
procedure_cpt_codes.c.cpt_code_id ],
primaryjoin = lambda: Procedure.id ==
procedure_cpt_codes.c.procedure_id,
secondaryjoin = lambda: CptCode.id ==
procedure_cpt_codes.c.cpt_code_id,
order_by = procedure_cpt_codes.c.cpt_codes_idx
)
procedure_date = Field(Date)

I get the following exception when run as listed:

Traceback (most recent call last):
  File /System/Library/Frameworks/Python.framework/Versions/Current/
Extras/lib/python/PyObjC/PyObjCTools/AppHelper.py, line 235, in
runEventLoop
main(argv)
  File /Users/tswall/Documents/workspace/Cocoa/python/Epdb/build/
Debug/Epdb.app/Contents/Resources/MyController.py, line 15, in
buttonPushed_
for instance in Patient.query.all():
  File /Library/Python/2.5/site-packages/Elixir-0.6.1-py2.5.egg/
elixir/entity.py, line 641, in __get__
elixir.setup_all()
  File /Library/Python/2.5/site-packages/Elixir-0.6.1-py2.5.egg/
elixir/__init__.py, line 145, in setup_all
  File /Library/Python/2.5/site-packages/Elixir-0.6.1-py2.5.egg/
elixir/entity.py, line 816, in setup_entities
method()
  File /Library/Python/2.5/site-packages/Elixir-0.6.1-py2.5.egg/
elixir/entity.py, line 421, in setup_properties
self.call_builders('create_properties')
  File /Library/Python/2.5/site-packages/Elixir-0.6.1-py2.5.egg/
elixir/entity.py, line 433, in call_builders
getattr(builder, what)()
  File /Library/Python/2.5/site-packages/Elixir-0.6.1-py2.5.egg/
elixir/relationships.py, line 417, in create_properties
self.target._descriptor.translate_order_by(kwargs['order_by'])
  File /Library/Python/2.5/site-packages/Elixir-0.6.1-py2.5.egg/
elixir/entity.py, line 322, in translate_order_by
for colname in order_by:
TypeError: 'Column' object is not iterable

When I change the order_by above to
  order_by = 'procedure_cpt_codes.c.cpt_codes_idx' #or 'cpt_codes_idx'
I get an error that it can't find column 'cpt_codes_idx' on relation
table 'CptCode'.

Any advice would be appreciated!
Scott

--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Using order_by in an association many-to-many relationship with columns from the association object

2006-10-29 Thread Raul Garcia
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 =