From: Mike Bayer Date: Wed, 24 Jan 2018 23:03:04 +0000 (-0500) Subject: Rework synonym, synonym_for documentation X-Git-Tag: rel_1_1_16~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f5b84ab2c53885c92926eab40032574fa5316425;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Rework synonym, synonym_for documentation The map_column example was incorrect, and overall the purpose of this parameter as well as that of synonym_for was not explained; examples added along with more encouragement to use hybrids. Change-Id: I20bd286f541f798daa81fa598c0f31db1f5aa6ed (cherry picked from commit 8250a4248fceaa3f4fbaebea3ff6a7f626299659) --- diff --git a/lib/sqlalchemy/ext/declarative/api.py b/lib/sqlalchemy/ext/declarative/api.py index 8d998b3b1d..d0746b2675 100644 --- a/lib/sqlalchemy/ext/declarative/api.py +++ b/lib/sqlalchemy/ext/declarative/api.py @@ -69,21 +69,36 @@ class DeclarativeMeta(type): def synonym_for(name, map_column=False): - """Decorator, make a Python @property a query synonym for a column. + """Decorator that produces an :func:`.orm.synonym` attribute in conjunction + with a Python descriptor. - A decorator version of :func:`~sqlalchemy.orm.synonym`. The function being - decorated is the 'descriptor', otherwise passes its arguments through to - synonym():: + The function being decorated is passed to :func:`.orm.synonym` as the + :paramref:`.orm.synonym.descriptor` parameter:: - @synonym_for('col') - @property - def prop(self): - return 'special sauce' + class MyClass(Base): + __tablename__ = 'my_table' + + id = Column(Integer, primary_key=True) + _job_status = Column("job_status", String(50)) + + @synonym_for("job_status") + @property + def job_status(self): + return "Status: %s" % self._job_status + + The :ref:`hybrid properties ` feature of SQLAlchemy + is typically preferred instead of synonyms, which is a more legacy + feature. + + .. seealso:: + + :ref:`synonyms` - Overview of synonyms - The regular ``synonym()`` is also usable directly in a declarative setting - and may be convenient for read/write properties:: + :func:`.orm.synonym` - the mapper-level function - prop = synonym('col', descriptor=property(_read_prop, _write_prop)) + :ref:`mapper_hybrids` - The Hybrid Attribute extension provides an + updated approach to augmenting attribute behavior more flexibly than + can be achieved with synonyms. """ def decorate(fn): diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py index 5882da0c8a..449ae6e6a5 100644 --- a/lib/sqlalchemy/orm/descriptor_props.py +++ b/lib/sqlalchemy/orm/descriptor_props.py @@ -503,8 +503,19 @@ class SynonymProperty(DescriptorProperty): in that the attribute will mirror the value and expression behavior of another attribute. + e.g.:: + + class MyClass(Base): + __tablename__ = 'my_table' + + id = Column(Integer, primary_key=True) + job_status = Column(String(50)) + + status = synonym("job_status") + + :param name: the name of the existing mapped property. This - can refer to the string name of any :class:`.MapperProperty` + can refer to the string name ORM-mapped attribute configured on the class, including column-bound attributes and relationships. @@ -512,26 +523,48 @@ class SynonymProperty(DescriptorProperty): 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:: + :param map_column: **For classical mappings and mappings against + an existing Table object only**. 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`. + This is intended to be used with the :paramref:`.synonym.descriptor` + parameter:: + + my_table = Table( + "my_table", metadata, + Column('id', Integer, primary_key=True), + Column('job_status', String(50)) + ) + + class MyClass(object): + @property + def _job_status_descriptor(self): + return "Status: %s" % self._job_status - class MyClass(Base): - __tablename__ = 'my_table' - id = Column(Integer, primary_key=True) - job_status = Column(String(50)) + mapper( + MyClass, my_table, properties={ + "job_status": synonym( + "_job_status", map_column=True, + descriptor=MyClass._job_status_descriptor) + } + ) - job_status = synonym("_job_status", map_column=True) + Above, the attribute named ``_job_status`` is automatically + mapped to the ``job_status`` column:: - 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. + >>> j1 = MyClass() + >>> j1._job_status = "employed" + >>> j1.job_status + Status: employed + + When using Declarative, in order to provide a descriptor in + conjunction with a synonym, use the + :func:`sqlalchemy.ext.declarative.synonym_for` helper. However, + note that the :ref:`hybrid properties ` feature + should usually be preferred, particularly when redefining attribute + behavior. :param info: Optional data dictionary which will be populated into the :attr:`.InspectionAttr.info` attribute of this object. @@ -551,10 +584,13 @@ class SynonymProperty(DescriptorProperty): .. seealso:: - :ref:`synonyms` - examples of functionality. + :ref:`synonyms` - Overview of synonyms + + :func:`.synonym_for` - a helper oriented towards Declarative - :ref:`mapper_hybrids` - Hybrids provide a better approach for - more complicated attribute-wrapping schemes than synonyms. + :ref:`mapper_hybrids` - The Hybrid Attribute extension provides an + updated approach to augmenting attribute behavior more flexibly + than can be achieved with synonyms. """ super(SynonymProperty, self).__init__()