def _relation_mapper(class_, table=None, secondary=None,
primaryjoin=None, secondaryjoin=None,
- foreignkey=None, uselist=None, private=False, live=False, association=None, lazy=True, selectalias=None, **kwargs):
+ foreignkey=None, uselist=None, private=False, live=False, association=None, lazy=True, selectalias=None, order_by=None, **kwargs):
return _relation_loader(mapper(class_, table, **kwargs), secondary, primaryjoin, secondaryjoin,
- foreignkey=foreignkey, uselist=uselist, private=private, live=live, association=association, lazy=lazy, selectalias=selectalias)
+ foreignkey=foreignkey, uselist=uselist, private=private, live=live, association=association, lazy=lazy, selectalias=selectalias, order_by=order_by)
class assignmapper(object):
"""provides a property object that will instantiate a Mapper for a given class the first
class_,
table,
primarytable = None,
- scope = "thread",
properties = None,
primary_key = None,
is_primary = False,
'class_':class_,
'table':table,
'primarytable':primarytable,
- 'scope':scope,
'properties':properties or {},
'primary_key':primary_key,
'is_primary':False,
self.extension = extension
self.hashkey = hashkey
self.class_ = class_
- self.scope = scope
self.is_primary = is_primary
if not issubclass(class_, object):
statement.use_labels = True
return statement
-
def _identity_key(self, row):
return objectstore.get_row_key(row, self.class_, self.primarytable, self.pks_by_table[self.table])
instance = imap[identitykey]
isnew = False
-
# plugin point
# call further mapper properties on the row, to pull further
return instance
-
class MapperProperty(object):
"""an element attached to a Mapper that describes and assists in the loading and saving
of an attribute on an object instance."""
def hash_key(obj):
if obj is None:
return 'None'
+ elif isinstance(obj, list):
+ return repr([hash_key(o) for o in obj])
elif hasattr(obj, 'hash_key'):
return obj.hash_key()
else:
return repr(obj)
-def mapper_hash_key(class_, table, primarytable = None, properties = None, scope = "thread", **kwargs):
+def mapper_hash_key(class_, table, primarytable = None, properties = None, **kwargs):
if properties is None:
properties = {}
return (
- "Mapper(%s, %s, primarytable=%s, properties=%s, scope=%s)" % (
+ "Mapper(%s, %s, primarytable=%s, properties=%s)" % (
repr(class_),
hash_key(table),
hash_key(primarytable),
- repr(dict([(k, hash_key(p)) for k,p in properties.iteritems()])),
- scope
+ repr(dict([(k, hash_key(p)) for k,p in properties.iteritems()]))
)
)
"""describes an object property that holds a single item or list of items that correspond
to a related database table."""
- def __init__(self, argument, secondary, primaryjoin, secondaryjoin, foreignkey=None, uselist=None, private=False, live=False, isoption=False, association=None, selectalias=None, **kwargs):
+ def __init__(self, argument, secondary, primaryjoin, secondaryjoin, foreignkey=None, uselist=None, private=False, live=False, isoption=False, association=None, selectalias=None, order_by=None, **kwargs):
self.uselist = uselist
self.argument = argument
self.secondary = secondary
self.isoption = isoption
self.association = association
self.selectalias = selectalias
- self._hash_key = "%s(%s, %s, %s, %s, %s, %s, %s)" % (self.__class__.__name__, hash_key(self.argument), hash_key(secondary), hash_key(primaryjoin), hash_key(secondaryjoin), hash_key(foreignkey), repr(uselist), repr(private))
+ self.order_by=util.to_list(order_by)
+ self._hash_key = "%s(%s, %s, %s, %s, %s, %s, %s, %s)" % (self.__class__.__name__, hash_key(self.argument), hash_key(secondary), hash_key(primaryjoin), hash_key(secondaryjoin), hash_key(foreignkey), repr(uselist), repr(private), hash_key(self.order_by))
def _copy(self):
return self.__class__(self.mapper, self.secondary, self.primaryjoin, self.secondaryjoin, self.foreignkey, self.uselist, self.private)
allparams = False
break
if allparams:
- if self.secondary is not None:
+ if self.order_by is not None:
+ order_by = self.order_by
+ elif self.secondary is not None:
order_by = [self.secondary.rowid_column]
else:
order_by = []
if self.secondaryjoin is not None:
statement._outerjoin = sql.outerjoin(towrap, self.secondary, self.primaryjoin).outerjoin(self.eagertarget, self.eagersecondary)
- statement.order_by(self.secondary.rowid_column)
+ if self.order_by is None:
+ statement.order_by(self.secondary.rowid_column)
else:
statement._outerjoin = towrap.outerjoin(self.eagertarget, self.eagerprimary)
- statement.order_by(self.eagertarget.rowid_column)
+ if self.order_by is None:
+ statement.order_by(self.eagertarget.rowid_column)
+ if self.order_by is not None:
+ statement.order_by(*[self.eagertarget.get_col_by_original(c) for c in self.order_by])
+
statement.append_from(statement._outerjoin)
statement.append_column(self.eagertarget)
recursion_stack[self] = True
__all__ = ['OrderedProperties', 'OrderedDict']
import thread, weakref, UserList,string
+def to_list(x):
+ if x is None:
+ return None
+ if not isinstance(x, list) and not isinstance(x, tuple):
+ return [x]
+
class OrderedProperties(object):
"""an object that maintains the order in which attributes are set upon it.
also provides an iterator and a very basic dictionary interface to those attributes.
{'user_id' : 7, 'addresses' : (Address, [{'address_id' : 1}])},
)
+ def testorderby(self):
+ m = mapper(Address, addresses)
+
+ m = mapper(User, users, properties = dict(
+ addresses = relation(m, lazy = True, order_by=addresses.c.email_address),
+ ))
+ l = m.select()
+ dict(address_id = 1, user_id = 7, email_address = "jack@bean.com"),
+ dict(address_id = 2, user_id = 8, email_address = "ed@wood.com"),
+ dict(address_id = 3, user_id = 8, email_address = "ed@lala.com")
+
+ self.assert_result(l, User,
+ {'user_id' : 7, 'addresses' : (Address, [{'email_address' : 'jack@bean.com'}])},
+ {'user_id' : 8, 'addresses' : (Address, [{'email_address':'ed@lala.com'}, {'email_address':'ed@wood.com'}])},
+ {'user_id' : 9, 'addresses' : (Address, [])}
+ )
+
def testonetoone(self):
m = mapper(User, users, properties = dict(
address = relation(Address, addresses, lazy = True, uselist = False)
{'user_id' : 9, 'addresses' : (Address, [])}
)
+ def testorderby(self):
+ m = mapper(Address, addresses)
+
+ m = mapper(User, users, properties = dict(
+ addresses = relation(m, lazy = False, order_by=addresses.c.email_address),
+ ))
+ l = m.select()
+ dict(address_id = 1, user_id = 7, email_address = "jack@bean.com"),
+ dict(address_id = 2, user_id = 8, email_address = "ed@wood.com"),
+ dict(address_id = 3, user_id = 8, email_address = "ed@lala.com")
+
+ self.assert_result(l, User,
+ {'user_id' : 7, 'addresses' : (Address, [{'email_address' : 'jack@bean.com'}])},
+ {'user_id' : 8, 'addresses' : (Address, [{'email_address':'ed@lala.com'}, {'email_address':'ed@wood.com'}])},
+ {'user_id' : 9, 'addresses' : (Address, [])}
+ )
+
def testonetoone(self):
m = mapper(User, users, properties = dict(
address = relation(Address, addresses, lazy = False, uselist = False)