so that :class:`_orm.declared_attr` methods can access the actual column
that will be mapped.
-Mixing in Association Proxy and Other Attributes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Mixins can specify user-defined attributes as well as other extension
-units such as :func:`.association_proxy`. The usage of
-:class:`_orm.declared_attr` is required in those cases where the attribute must
-be tailored specifically to the target subclass. An example is when
-constructing multiple :func:`.association_proxy` attributes which each
-target a different type of child object. Below is an
-:func:`.association_proxy` mixin example which provides a scalar list of
-string values to an implementing class::
-
- from sqlalchemy import Column, ForeignKey, Integer, String
- from sqlalchemy.ext.associationproxy import association_proxy
- from sqlalchemy.orm import (
- declarative_base,
- declarative_mixin,
- declared_attr,
- relationship,
- )
-
- Base = declarative_base()
-
-
- @declarative_mixin
- class HasStringCollection:
- @declared_attr
- def _strings(cls):
- class StringAttribute(Base):
- __tablename__ = cls.string_table_name
- id = Column(Integer, primary_key=True)
- value = Column(String(50), nullable=False)
- parent_id = Column(
- Integer,
- ForeignKey(f"{cls.__tablename__}.id"),
- nullable=False,
- )
-
- def __init__(self, value):
- self.value = value
-
- return relationship(StringAttribute)
-
- @declared_attr
- def strings(cls):
- return association_proxy("_strings", "value")
-
-
- class TypeA(HasStringCollection, Base):
- __tablename__ = "type_a"
- string_table_name = "type_a_strings"
- id = Column(Integer(), primary_key=True)
-
-
- class TypeB(HasStringCollection, Base):
- __tablename__ = "type_b"
- string_table_name = "type_b_strings"
- id = Column(Integer(), primary_key=True)
-
-Above, the ``HasStringCollection`` mixin produces a :func:`_orm.relationship`
-which refers to a newly generated class called ``StringAttribute``. The
-``StringAttribute`` class is generated with its own :class:`_schema.Table`
-definition which is local to the parent class making usage of the
-``HasStringCollection`` mixin. It also produces an :func:`.association_proxy`
-object which proxies references to the ``strings`` attribute onto the ``value``
-attribute of each ``StringAttribute`` instance.
-
-``TypeA`` or ``TypeB`` can be instantiated given the constructor
-argument ``strings``, a list of strings::
-
- ta = TypeA(strings=["foo", "bar"])
- tb = TypeB(strings=["bat", "bar"])
-
-This list will generate a collection
-of ``StringAttribute`` objects, which are persisted into a table that's
-local to either the ``type_a_strings`` or ``type_b_strings`` table::
-
- >>> print(ta._strings)
- [<__main__.StringAttribute object at 0x10151cd90>,
- <__main__.StringAttribute object at 0x10151ce10>]
-
-When constructing the :func:`.association_proxy`, the
-:class:`_orm.declared_attr` decorator must be used so that a distinct
-:func:`.association_proxy` object is created for each of the ``TypeA``
-and ``TypeB`` classes.
-
.. _decl_mixin_inheritance:
Controlling table inheritance with mixins