1. Daniel Miller
  2. sqlalchemy

Commits

Mike Bayer  committed 3430c8b

added "synonym()" function, applied to properties to have a
propname the same as another, for the purposes of overriding props
and allowing the original propname to be accessible in select_by().

  • Participants
  • Parent commits 33b9fe2
  • Branches default

Comments (0)

Files changed (5)

File CHANGES

View file
 a flush() under some circumstances, this was fixed
 - expunge() was not working with cascade, fixed.
 - potential endless loop in cascading operations fixed.
+- added "synonym()" function, applied to properties to have a 
+propname the same as another, for the purposes of overriding props
+and allowing the original propname to be accessible in select_by().
 
 0.2.5
 - fixed endless loop bug in select_by(), if the traversal hit

File doc/build/content/adv_datamapping.txt

View file
        '_email': mytable.c.email
     })
 
-In a later release, SQLAlchemy will also allow `_get_email` and `_set_email` to be attached directly to the "email" property created by the mapper, and 
-will also allow this association to occur via decorators.
+It is also possible to use the `select_by` and `get_by` functions on `Query` using the original property name, by establishing a `synonym`:
 
+    {python}
+    mapper(MyClass, mytable, proeprties = {
+        # map the '_email' attribute to the "email" column
+        # on the table
+        '_email': mytable.c.email
+
+        # make a synonym 'email'
+        'email' : synonym('_email')
+    })
+    
+    # now you can select_by(email)
+    result = session.query(MyClass).select_by(email='john@smith.com')
+
+The `synonym` keyword is currently an [Alpha Feature][alpha_api].
 
 #### Custom List Classes {@name=customlist}
 

File lib/sqlalchemy/orm/__init__.py

View file
 
 __all__ = ['relation', 'backref', 'eagerload', 'lazyload', 'noload', 'deferred', 'defer', 'undefer',
         'mapper', 'clear_mappers', 'sql', 'extension', 'class_mapper', 'object_mapper', 'MapperExtension', 'Query', 
-        'cascade_mappers', 'polymorphic_union', 'create_session', 'EXT_PASS' 
+        'cascade_mappers', 'polymorphic_union', 'create_session', 'synonym', 'EXT_PASS' 
         ]
 
 def relation(*args, **kwargs):
     """returns a newMapper object."""
     return Mapper(class_, table, *args, **params)
 
+def synonym(name):
+    return SynonymProperty(name)
+    
 def clear_mappers():
     """removes all mappers that have been created thus far.  when new mappers are 
     created, they will be assigned to their classes as their primary mapper."""

File lib/sqlalchemy/orm/mapper.py

View file
 import session as sessionlib
 import weakref
 
-__all__ = ['Mapper', 'MapperExtension', 'class_mapper', 'object_mapper', 'EXT_PASS']
+__all__ = ['Mapper', 'MapperExtension', 'class_mapper', 'object_mapper', 'SynonymProperty', 'EXT_PASS']
 
 # a dictionary mapping classes to their primary mappers
 mapper_registry = weakref.WeakKeyDictionary()
         at the class level.  otherwise we have to set attribute behavior on a per-instance level."""
         return self.parent._is_primary_mapper()
 
+class SynonymProperty(MapperProperty):
+    """a marker object used by query.select_by to allow a property name to refer to another.
+    
+    this object may be expanded in the future."""
+    def __init__(self, name):
+        self.name = name
+    def execute(self, session, instance, row, identitykey, imap, isnew):
+        pass
+    def copy(self):
+        return SynonymProperty(self.name)
+        
 class MapperOption(object):
     """describes a modification to a Mapper in the context of making a copy
     of it.  This is used to assist in the prototype pattern used by mapper.options()."""

File lib/sqlalchemy/orm/query.py

View file
         import properties
         keys = []
         seen = util.Set()
-        def search_for_prop(mapper):
-            if mapper in seen:
+        def search_for_prop(mapper_):
+            if mapper_ in seen:
                 return None
-            seen.add(mapper)
-            if mapper.props.has_key(key):
-                prop = mapper.props[key]
+            seen.add(mapper_)
+            if mapper_.props.has_key(key):
+                prop = mapper_.props[key]
+                if isinstance(prop, mapper.SynonymProperty):
+                    prop = mapper_.props[prop.name]
                 if isinstance(prop, properties.PropertyLoader):
                     keys.insert(0, prop.key)
                 return prop
             else:
-                for prop in mapper.props.values():
+                for prop in mapper_.props.values():
                     if not isinstance(prop, properties.PropertyLoader):
                         continue
                     x = search_for_prop(prop.mapper)