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 -~----------~----~----~----~------~----~------~--~---