]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- re-document synonyms and remove warnings about "superseded"; synonyms
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 30 Nov 2013 20:30:24 +0000 (15:30 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 30 Nov 2013 20:30:24 +0000 (15:30 -0500)
are still useful, just include notes that for more complex descriptor operations,
hybrids are probably preferable

doc/build/orm/mapper_config.rst
lib/sqlalchemy/orm/descriptor_props.py

index 9cd9abaca43f573d77082ff80d024256c41d5688..37d9a33e6d907743285d162cad726d81fc2381a0 100644 (file)
@@ -689,13 +689,13 @@ described at :class:`~.AttributeEvents`.
 
 .. autofunction:: validates
 
-.. _synonyms:
+.. _mapper_hybrids:
 
 Using Descriptors and Hybrids
 -----------------------------
 
 A more comprehensive way to produce modified behavior for an attribute is to
-use descriptors. These are commonly used in Python using the ``property()``
+use :term:`descriptors`.  These are commonly used in Python using the ``property()``
 function. The standard SQLAlchemy technique for descriptors is to create a
 plain descriptor, and to have it read/write from a mapped attribute with a
 different name. Below we illustrate this using Python 2.6-style properties::
@@ -819,14 +819,88 @@ attribute, a SQL function is rendered which produces the same effect:
 
 Read more about Hybrids at :ref:`hybrids_toplevel`.
 
+.. _synonyms:
+
 Synonyms
 --------
 
-Synonyms are a mapper-level construct that applies expression behavior to a descriptor
-based attribute.
+Synonyms are a mapper-level construct that allow any attribute on a class
+to "mirror" another attribute that is mapped.
 
-.. versionchanged:: 0.7
-    The functionality of synonym is superceded as of 0.7 by hybrid attributes.
+In the most basic sense, the synonym is an easy way to make a certain
+attribute available by an additional name::
+
+    class MyClass(Base):
+        __tablename__ = 'my_table'
+
+        id = Column(Integer, primary_key=True)
+        job_status = Column(String(50))
+
+        status = synonym("job_status")
+
+The above class ``MyClass`` has two attributes, ``.job_status`` and
+``.status`` that will behave as one attribute, both at the expression
+level::
+
+    >>> print MyClass.job_status == 'some_status'
+    my_table.job_status = :job_status_1
+
+    >>> print MyClass.status == 'some_status'
+    my_table.job_status = :job_status_1
+
+and at the instance level::
+
+    >>> m1 = MyClass(status='x')
+    >>> m1.status, m1.job_status
+    ('x', 'x')
+
+    >>> m1.job_status = 'y'
+    >>> m1.status, m1.job_status
+    ('y', 'y')
+
+The :func:`.synonym` can be used for any kind of mapped attribute that
+subclasses :class:`.MapperProperty`, including mapped columns and relationships,
+as well as synonyms themselves.
+
+Beyond a simple mirror, :func:`.synonym` can also be made to reference
+a user-defined :term:`descriptor`.  We can supply our
+``status`` synonym with a ``@property``::
+
+    class MyClass(Base):
+        __tablename__ = 'my_table'
+
+        id = Column(Integer, primary_key=True)
+        status = Column(String(50))
+
+        @property
+        def job_status(self):
+            return "Status: " + self.status
+
+        job_status = synonym("status", descriptor=job_status)
+
+When using Declarative, the above pattern can be expressed more succinctly
+using the :func:`.synonym_for` decorator::
+
+    from sqlalchemy.ext.declarative import synonym_for
+
+    class MyClass(Base):
+        __tablename__ = 'my_table'
+
+        id = Column(Integer, primary_key=True)
+        status = Column(String(50))
+
+        @synonym_for("status")
+        @property
+        def job_status(self):
+            return "Status: " + self.status
+
+While the :func:`.synonym` is useful for simple mirroring, the use case
+of augmenting attribute behavior with descriptors is better handled in modern
+usage using the :ref:`hybrid attribute <mapper_hybrids>` feature, which
+is more oriented towards Python descriptors.   Techically, a :func:`.synonym`
+can do everything that a :class:`.hybrid_property` can do, as it also supports
+injection of custom SQL capabilities, but the hybrid is more straightforward
+to use in more complex situations.
 
 .. autofunction:: synonym
 
index daf125ea23212b19e9da053acb8a1eb7baf683f2..1156a140e98a30c381cb52c2f0ac3ee29523435e 100644 (file)
@@ -488,40 +488,57 @@ class SynonymProperty(DescriptorProperty):
     def __init__(self, name, map_column=None,
                             descriptor=None, comparator_factory=None,
                             doc=None):
-        """Denote an attribute name as a synonym to a mapped property.
+        """Denote an attribute name as a synonym to a mapped property,
+        in that the attribute will mirror the value and expression behavior
+        of another attribute.
 
-        .. versionchanged:: 0.7
-            :func:`.synonym` is superseded by the :mod:`~sqlalchemy.ext.hybrid`
-            extension.  See  the documentation for hybrids
-            at :ref:`hybrids_toplevel`.
-
-        Used with the ``properties`` dictionary sent to
-        :func:`~sqlalchemy.orm.mapper`::
-
-            class MyClass(object):
-                def _get_status(self):
-                    return self._status
-                def _set_status(self, value):
-                    self._status = value
-                status = property(_get_status, _set_status)
-
-            mapper(MyClass, sometable, properties={
-                "status":synonym("_status", map_column=True)
-            })
-
-        Above, the ``status`` attribute of MyClass will produce
-        expression behavior against the table column named ``status``,
-        using the Python attribute ``_status`` on the mapped class
-        to represent the underlying value.
-
-        :param name: the name of the existing mapped property, which can be
-          any other ``MapperProperty`` including column-based properties and
-          relationships.
-
-        :param map_column: if ``True``, an additional ``ColumnProperty`` is created
-          on the mapper automatically, using the synonym's name as the keyname of
-          the property, and the keyname of this ``synonym()`` as the name of the
-          column to map.
+        :param name: the name of the existing mapped property.  This
+          can refer to the string name of any :class:`.MapperProperty`
+          configured on the class, including column-bound attributes
+          and relationships.
+
+        :param descriptor: a Python :term:`descriptor` that will be used
+          as a getter (and potentially a setter) when this attribute is
+          accessed at the instance level.
+
+        :param map_column: if ``True``, the :func:`.synonym` construct will
+          locate the existing named :class:`.MapperProperty` based on the
+          attribute name of this :func:`.synonym`, and assign it to a new
+          attribute linked to the name of this :func:`.synonym`.
+          That is, given a mapping like::
+
+                class MyClass(Base):
+                    __tablename__ = 'my_table'
+
+                    id = Column(Integer, primary_key=True)
+                    job_status = Column(String(50))
+
+                    job_status = synonym("_job_status", map_column=True)
+
+          The above class ``MyClass`` will now have the ``job_status``
+          :class:`.Column` object mapped to the attribute named ``_job_status``,
+          and the attribute named ``job_status`` will refer to the synonym
+          itself.  This feature is typically used in conjunction with the
+          ``descriptor`` argument in order to link a user-defined descriptor
+          as a "wrapper" for an existing column.
+
+        :param comparator_factory: A subclass of :class:`.PropComparator`
+          that will provide custom comparison behavior at the SQL expression
+          level.
+
+          .. note::
+
+            For the use case of providing an attribute which redefines both
+            Python-level and SQL-expression level behavior of an attribute,
+            please refer to the Hybrid attribute introduced at
+            :ref:`mapper_hybrids` for a more effective technique.
+
+        .. seealso::
+
+            :ref:`synonyms` - examples of functionality.
+
+            :ref:`mapper_hybrids` - Hybrids provide a better approach for
+            more complicated attribute-wrapping schemes than synonyms.
 
         """