[sqlalchemy] Behavior question with association proxy with custom collection class

2008-02-21 Thread Ronald Lew

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



[sqlalchemy] Re: Behavior question with association proxy with custom collection class

2008-02-21 Thread Ronald Lew

I assume a getset_factory is needed for the association proxy.  Any
examples?

On Feb 21, 8:38 am, Ronald Lew [EMAIL PROTECTED] 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)

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



[sqlalchemy] Collection class using OrderedDict and MappedCollection

2007-12-04 Thread Ronald Lew

I am creating a Collection class using the OrderedDict and
MappedCollection with primary key id as the key index.  The problem,
as noted in the docs, is that the key should be an immutable field.
Since I am using a primary key, the value will change when I am
instantiating a new object and adding it to the collection.  The code
illustrates my concept:

class Collection(OrderedDict, MappedCollection):
   def __init__(self, *args, **kwargs):
  MappedCollection.__init__(self, keyfunc=lambda item: item.id)
  OrderedDict.__init__(self, *args, **kwargs)

def refresh(self, *args, **kwargs):
 Updates all keys based on the keyfunc and each current
value
dict_copy = self.copy()
self.clear()
for item in dict_copy.values():
MappedCollection.set(self, item)


class Parent(Base): pass

class Child(Base): pass

session.mapper(class_=Child, local_table=child_table)

session.mapper(class_=Parent, local_table=parent_table,
   properties={'childs':relation(Child, backref='parent',
collection_class=ChildCollection)})


some_collection = ChildCollection()
new_child = Child(id=None, data='foo')
some_collection.set(new_child) # key is None, id is None

session.save(some_collection.values()) # save the child

# at this point, key is still None, but id is 1

some_collection.refresh() # key will be 1.
# I would like the refresh behavior to be invoked during/after a
flush.


Now, if I saved the Child under the Parent, then the key index would
have been updated automatically like so:
my_parent = Parent
Parent.childs.set(new_child)
session.save(Parent)
# The childs index will be 1
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Overriding mapper relation

2007-11-28 Thread Ronald Lew

I have a customer table which has a 1-to-n relation with a phone
table.  The phone table has the following columns: integer id, string
number, and boolean is_fax.  Is there a way to override the phones
collection so I can return a boolean if the customer contains at least
1 phone record with a is_fax set to True.


For example:

class Customer: pass
class Phone: pass

session.mapper(Customer, customers_table,
properties={'phones':relation(Phone, backref='customers'})

my_customer = Customer.query.filter_by(id=1).first()

# I want it to return True if at least one phone in the list has
is_fax = True
# so I'm thinking of somehow wrapping or overriding the python list
class
my_customer.phones.has_fax()
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Using column_property for flagging purpose

2007-11-15 Thread Ronald Lew

I am having issues creating a read-only column using column_property.
I have a phone table that has the columns: id, country_code, number,
and deleted.  I want to have an international column which will be set
to True or False (or 1 or 0) depending on the value of the
country_code.  Provided below is the snippet of code to work with:

phone_table = Table('phones', metadata,
Column('id', Integer, primary_key=True),
Column('country_code', String(5)),
Column('number', String(20)),
Column('deleted', Boolean, default=False),
)

class Phone(object):
pass

# international gets set to True or None which isn't intended
# also the session is from turbogears.database import session
session.mapper(Phone, phone_table, properties={
 
'international':column_property((phone_table.c.country_code=='1').label('international'))
})



I'm not sure if this is a Turbogears issue or SQLAlchemy issue but the
international field is always None when I do the following: I
instantiate a Phone object, populate the attributes, session.save the
instantiated Phone object, session.flush, and then query the new Phone
object.
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---