I wanted to use a mapped collection or a customized collection instead
of the default list for the collection class and have the keyword's id
as the key.  In addition, I wanted to keep using the append but that
seems impossible now since I cannot fool association dict to use it.
I wanted to not have to change the below code:

for kw in (Keyword('1','one'), Keyword('2','two'),
Keyword('3','three')):
    user.keywords.append(kw) # cannot use this any more


On Feb 21, 9:23 am, jason kirtland <[EMAIL PROTECTED]> wrote:
> 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