Ronald Lew wrote:
> I was exploring the association proxy example in the documentation and
> then explored the use of a mapped collection as the custom collection
> class with mixed results.  When attempting to "append", an
> AttributeError _AssociationDict object has no attribute append
> occurred.  Then, I tried subclassing MappedCollection, created my own
> append method and have SQLAlchemy instrument it but the results were
> the same.  Here's the code I was testing it with:
> 
> from sqlalchemy import Boolean, Column, ForeignKey, Integer, String,
> Table
> from sqlalchemy.orm import relation
> from sqlalchemy.orm.collections import mapped_collection,
> MappedCollection, collection
> from sqlalchemy.ext.associationproxy import association_proxy
> from turbogears.database import metadata, session
> 
> users_table = Table('users', metadata,
>     Column('id', Integer, primary_key=True),
>     Column('name', String(64))
> )
> 
> keywords_table = Table('keywords', metadata,
>     Column('id', Integer, primary_key=True),
>     Column('keyword', String(64))
> )
> 
> userkeywords_table = Table('userkeywords', metadata,
>     Column('user_id', Integer, ForeignKey("users.id"),
> primary_key=True),
>     Column('keyword_id', Integer, ForeignKey("keywords.id"),
> primary_key=True)
> )
> 
> def _create_uk(keyword):
>     return UserKeyword(keyword=keyword)
> 
> class User(object):
>     def __init__(self, id, name):
>         self.id = id
>         self.name = name
>     keywords = association_proxy('user_keywords', 'keyword',
> creator=_create_uk)
> 
> class Keyword(object):
>     def __init__(self, id, keyword):
>         self.id = id
>         self.keyword = keyword
>     def __repr__(self):
>         return 'Keyword(%s)' % repr(self.keyword)
> 
> class UserKeyword(object):
>     def __init__(self, user=None, keyword=None):
>         self.user = user
>         self.keyword = keyword
> 
> session.mapper(Keyword, keywords_table)
> session.mapper(User, users_table, properties={
>     'user_keywords':relation(UserKeyword)
> })
> session.mapper(UserKeyword, userkeywords_table, properties={
>     'user':relation(User),
>     'keyword':relation(Keyword)
> })
> 
> user = User('1', 'number')
> kw1 = Keyword('0', 'zero')
> user.user_keywords.append(UserKeyword(user, kw1))
> 
> for kw in (Keyword('1', 'one'), Keyword('2', 'two'), Keyword('3',
> 'three')):
>     user.keywords.append(kw)
> 
> 
> Portion of code changed with mapped collection (which won't work):
> session.mapper(User, users_table, properties={
>     #'user_keywords':relation(UserKeyword)
>     'user_keywords':relation(UserKeyword,
> collection_class=mapped_collection(lambda item: item.keyword.id))
> })
> 
> 
> Code for customized collection (also won't work):
> class MyCollection(MappedCollection):
>     def __init__(self, keyfunc=lambda item: item.id):
>         MappedCollection.__init__(self, keyfunc=keyfunc)
> 
>     @collection.appender
>     def append(self, item):
>         MappedCollection.set(self, item)
> 
>     @collection.remover
>     def remove(self, item):
>         MappedCollection.remove(self, item)
> 
> u_collection = lambda: MyCollection(keyfunc=lambda item:
> item.keyword.id)
> session.mapper(User, users_table, properties={
>     #'user_keywords':relation(UserKeyword)
>     'user_keywords':relation(UserKeyword,
> collection_class=u_collection)
> })

The association proxy chooses an interface that mimics the Python 
collection type closest to the underlying collection class.  So with the 
dict-like collection class, you'll get a dict proxy.

Unless there's more going on that's not included in this example, I'm 
not clear on what the mapped collection or proxies are doing in this 
mapping...  The userkeywords_table can be used as an association table 
instead of being mapped, and a regular list relation will get you a 
'user.keywords' of associated Keyword objects.

Or if you're planning on adding attributes to userkeywords_table, then 
you do need to map the table as UserKeyword but a regular list relation 
plus association proxy would still be my first choice.


--~--~---------~--~----~------------~-------~--~----~
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?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to