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 [email protected]
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
-~----------~----~----~----~------~----~------~--~---