>>> str(EmailAddress.email == 'SomeAddress@foo.com')
lower(addresses.email) = lower(:lower_1)
-The ``__clause_element__()`` method is provided by the base ``Comparator`` class in use, and represents the SQL element which best matches what this attribute represents. For a column-based attribute, it's the mapped column. For a composite attribute, it's a :class:`~sqlalchemy.sql.expression.ClauseList` consisting of each column represented. For a relation, it's the table mapped by the local mapper (not the remote mapper). ``__clause_element__()`` should be honored by the custom comparator class in most cases since the resulting element will be applied any translations which are in effect, such as the correctly aliased member when using an ``aliased()`` construct or certain ``with_polymorphic()`` scenarios.
+The ``__clause_element__()`` method is provided by the base ``Comparator`` class in use, and represents the SQL element which best matches what this attribute represents. For a column-based attribute, it's the mapped column. For a composite attribute, it's a :class:`~sqlalchemy.sql.expression.ClauseList` consisting of each column represented. For a relation, it's the table mapped by the local mapper (not the remote mapper). ``__clause_element__()`` should be honored by the custom comparator class in most cases since the resulting element will be applied any translations which are in effect, such as the correctly aliased member when using an ``aliased()`` construct or certain :func:`~sqlalchemy.orm.query.Query.with_polymorphic` scenarios.
There are four kinds of ``Comparator`` classes which may be subclassed, as according to the type of mapper property configured:
When using :func:`~sqlalchemy.orm.comparable_property`, which is a mapper property that isn't tied to any column or mapped table, the ``__clause_element__()`` method of :class:`~sqlalchemy.orm.interfaces.PropComparator` should also be implemented.
-The ``comparator_factory`` argument is accepted by all ``MapperProperty``-producing functions: :func:`~sqlalchemy.orm.column_property`, :func:`~sqlalchemy.orm.composite`, :func:`~sqlalchemy.orm.comparable_property`, :func:`~sqlalchemy.orm.synonym`, :func:`~sqlalchemy.orm.relation`, ``backref()``, :func:`~sqlalchemy.orm.deferred`, and :func:`~sqlalchemy.orm.dynamic_loader`.
+The ``comparator_factory`` argument is accepted by all ``MapperProperty``-producing functions: :func:`~sqlalchemy.orm.column_property`, :func:`~sqlalchemy.orm.composite`, :func:`~sqlalchemy.orm.comparable_property`, :func:`~sqlalchemy.orm.synonym`, :func:`~sqlalchemy.orm.relation`, :func:`~sqlalchemy.orm.backref`, :func:`~sqlalchemy.orm.deferred`, and :func:`~sqlalchemy.orm.dynamic_loader`.
Composite Column Types
-----------------------
Controlling Which Tables are Queried
+++++++++++++++++++++++++++++++++++++
-The ``with_polymorphic()`` method of :class:`~sqlalchemy.orm.query.Query` affects the specific subclass tables which the Query selects from. Normally, a query such as this:
+The :func:`~sqlalchemy.orm.query.Query.with_polymorphic` method of :class:`~sqlalchemy.orm.query.Query` affects the specific subclass tables which the Query selects from. Normally, a query such as this:
.. sourcecode:: python+sql
FROM employees LEFT OUTER JOIN engineers ON employees.employee_id = engineers.employee_id LEFT OUTER JOIN managers ON employees.employee_id = managers.employee_id
[]
-``with_polymorphic()`` accepts a single class or mapper, a list of classes/mappers, or the string ``'*'`` to indicate all subclasses:
+:func:`~sqlalchemy.orm.query.Query.with_polymorphic` accepts a single class or mapper, a list of classes/mappers, or the string ``'*'`` to indicate all subclasses:
.. sourcecode:: python+sql
# custom selectable
query.with_polymorphic([Engineer, Manager], employees.outerjoin(managers).outerjoin(engineers))
-``with_polymorphic()`` is also needed when you wish to add filter criterion that is specific to one or more subclasses, so that those columns are available to the WHERE clause:
+:func:`~sqlalchemy.orm.query.Query.with_polymorphic` is also needed when you wish to add filter criterion that is specific to one or more subclasses, so that those columns are available to the WHERE clause:
.. sourcecode:: python+sql
session.query(Employee).with_polymorphic([Engineer, Manager]).\
filter(or_(Engineer.engineer_info=='w', Manager.manager_data=='q'))
-Note that if you only need to load a single subtype, such as just the ``Engineer`` objects, ``with_polymorphic()`` is not needed since you would query against the ``Engineer`` class directly.
+Note that if you only need to load a single subtype, such as just the ``Engineer`` objects, :func:`~sqlalchemy.orm.query.Query.with_polymorphic` is not needed since you would query against the ``Engineer`` class directly.
The mapper also accepts ``with_polymorphic`` as a configurational argument so that the joined-style load will be issued automatically. This argument may be the string ``'*'``, a list of classes, or a tuple consisting of either, followed by a selectable.
The above mapping will produce a query similar to that of ``with_polymorphic('*')`` for every query of ``Employee`` objects.
-Using ``with_polymorphic()`` with :class:`~sqlalchemy.orm.query.Query` will override the mapper-level ``with_polymorphic`` setting.
+Using :func:`~sqlalchemy.orm.query.Query.with_polymorphic` with :class:`~sqlalchemy.orm.query.Query` will override the mapper-level ``with_polymorphic`` setting.
Creating Joins to Specific Subtypes
++++++++++++++++++++++++++++++++++++
'children': relation(Child, lazy=False)
})
-The loader strategy can be changed from lazy to eager as well as eager to lazy using the ``eagerload()`` and ``lazyload()`` query options:
+The loader strategy can be changed from lazy to eager as well as eager to lazy using the :func:`~sqlalchemy.orm.eagerload` and :func:`~sqlalchemy.orm.lazyload` query options:
.. sourcecode:: python+sql
session.query(Parent).options(eagerload('foo.bar.bat')).all()
-When using dot-separated names with ``eagerload()``, option applies **only** to the actual attribute named, and **not** its ancestors. For example, suppose a mapping from ``A`` to ``B`` to ``C``, where the relations, named ``atob`` and ``btoc``, are both lazy-loading. A statement like the following:
+When using dot-separated names with :func:`~sqlalchemy.orm.eagerload`, option applies **only** to the actual attribute named, and **not** its ancestors. For example, suppose a mapping from ``A`` to ``B`` to ``C``, where the relations, named ``atob`` and ``btoc``, are both lazy-loading. A statement like the following:
.. sourcecode:: python+sql
session.query(A).options(eagerload('atob'), eagerload('atob.btoc')).all()
-or more simply just use ``eagerload_all()``:
+or more simply just use :func:`~sqlalchemy.orm.eagerload_all`:
.. sourcecode:: python+sql
session.query(User).outerjoin(User.addresses).options(contains_eager(User.addresses)).all()
-If the "eager" portion of the statement is "aliased", the ``alias`` keyword argument to ``contains_eager()`` may be used to indicate it. This is a string alias name or reference to an actual :class:`~sqlalchemy.sql.expression.Alias` (or other selectable) object:
+If the "eager" portion of the statement is "aliased", the ``alias`` keyword argument to :func:`~sqlalchemy.orm.contains_eager` may be used to indicate it. This is a string alias name or reference to an actual :class:`~sqlalchemy.sql.expression.Alias` (or other selectable) object:
.. sourcecode:: python+sql
"from users left outer join addresses on users.user_id=addresses.user_id").\
options(contains_eager(User.addresses, alias=eager_columns))
-The path given as the argument to ``contains_eager()`` needs to be a full path from the starting entity. For example if we were loading ``Users->orders->Order->items->Item``, the string version would look like::
+The path given as the argument to :func:`~sqlalchemy.orm.contains_eager` needs to be a full path from the starting entity. For example if we were loading ``Users->orders->Order->items->Item``, the string version would look like::
query(User).options(contains_eager('orders', 'items'))
query(User).options(contains_eager(User.orders, Order.items))
-A variant on ``contains_eager()`` is the ``contains_alias()`` option, which is used in the rare case that the parent object is loaded from an alias within a user-defined SELECT statement::
+A variant on :func:`~sqlalchemy.orm.contains_eager` is the ``contains_alias()`` option, which is used in the rare case that the parent object is loaded from an alias within a user-defined SELECT statement::
# define an aliased UNION called 'ulist'
statement = users.select(users.c.user_id==7).union(users.select(users.c.user_id>7)).alias('ulist')
~~~~~~~~~~~~~~~~~~~~~~~~~
-The most useful by far is the :func:`~sqlalchemy.orm.dynamic_loader` relation. This is a variant of :func:`~sqlalchemy.orm.relation` which returns a :class:`~sqlalchemy.orm.query.Query` object in place of a collection when accessed. ``filter()`` criterion may be applied as well as limits and offsets, either explicitly or via array slices:
+The most useful by far is the :func:`~sqlalchemy.orm.dynamic_loader` relation. This is a variant of :func:`~sqlalchemy.orm.relation` which returns a :class:`~sqlalchemy.orm.query.Query` object in place of a collection when accessed. :func:`~sqlalchemy.orm.query.Query.filter` criterion may be applied as well as limits and offsets, either explicitly or via array slices:
.. sourcecode:: python+sql
('Ed Jones',)
{stop}ed
-...or ``filter()``, which uses more flexible SQL expression language constructs. These allow you to use regular Python operators with the class-level attributes on your mapped class:
+...or :func:`~sqlalchemy.orm.query.Query.filter`, which uses more flexible SQL expression language constructs. These allow you to use regular Python operators with the class-level attributes on your mapped class:
.. sourcecode:: python+sql
('Ed Jones',)
{stop}ed
-The :class:`~sqlalchemy.orm.query.Query` object is fully *generative*, meaning that most method calls return a new :class:`~sqlalchemy.orm.query.Query` object upon which further criteria may be added. For example, to query for users named "ed" with a full name of "Ed Jones", you can call ``filter()`` twice, which joins criteria using ``AND``:
+The :class:`~sqlalchemy.orm.query.Query` object is fully *generative*, meaning that most method calls return a new :class:`~sqlalchemy.orm.query.Query` object upon which further criteria may be added. For example, to query for users named "ed" with a full name of "Ed Jones", you can call :func:`~sqlalchemy.orm.query.Query.filter` twice, which joins criteria using ``AND``:
.. sourcecode:: python+sql
Common Filter Operators
-----------------------
-Here's a rundown of some of the most common operators used in ``filter()``:
+Here's a rundown of some of the most common operators used in :func:`~sqlalchemy.orm.query.Query.filter`:
* equals::
The many-to-many relation is also bi-directional using the ``backref`` keyword. This is the one case where usage of ``backref`` is generally required, since if a separate ``posts`` relation were added to the ``Keyword`` entity, both relations would independently add and remove rows from the ``post_keywords`` table and produce conflicts.
-We would also like our ``BlogPost`` class to have an ``author`` field. We will add this as another bidirectional relationship, except one issue we'll have is that a single user might have lots of blog posts. When we access ``User.posts``, we'd like to be able to filter results further so as not to load the entire collection. For this we use a setting accepted by :func:`~sqlalchemy.orm.relation` called ``lazy='dynamic'``, which configures an alternate **loader strategy** on the attribute. To use it on the "reverse" side of a :func:`~sqlalchemy.orm.relation`, we use the ``backref()`` function:
+We would also like our ``BlogPost`` class to have an ``author`` field. We will add this as another bidirectional relationship, except one issue we'll have is that a single user might have lots of blog posts. When we access ``User.posts``, we'd like to be able to filter results further so as not to load the entire collection. For this we use a setting accepted by :func:`~sqlalchemy.orm.relation` called ``lazy='dynamic'``, which configures an alternate **loader strategy** on the attribute. To use it on the "reverse" side of a :func:`~sqlalchemy.orm.relation`, we use the :func:`~sqlalchemy.orm.backref` function:
.. sourcecode:: python+sql