summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-11-27 14:29:00 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2021-11-27 14:30:56 -0500
commit29c5fba9ad89e53180f0bd2a026742321093105f (patch)
tree971ca37f3864802594997ce9f231c2b53528e6ad
parent6e789bcc9758fd951d3196b38bf1ad0c9b4ab0e5 (diff)
downloadsqlalchemy-29c5fba9ad89e53180f0bd2a026742321093105f.tar.gz
update migration strategy for dynamic loaders
discuss the two current ways for this use case that use 2.0 style querying and introduce that a newer API is likely on the way. Also repair autofunctions for with_parent for 2.0 only. References: #7123 References: #7372 Change-Id: I2ff6cfd780540ee4ee887b61137af7afa1327a9f
-rw-r--r--doc/build/changelog/migration_20.rst59
-rw-r--r--doc/build/orm/collections.rst8
-rw-r--r--doc/build/orm/extensions/asyncio.rst4
-rw-r--r--doc/build/orm/queryguide.rst6
4 files changed, 70 insertions, 7 deletions
diff --git a/doc/build/changelog/migration_20.rst b/doc/build/changelog/migration_20.rst
index 1c0169888..5fdd093d0 100644
--- a/doc/build/changelog/migration_20.rst
+++ b/doc/build/changelog/migration_20.rst
@@ -2049,6 +2049,65 @@ the :func:`_orm.selectinload` strategy presents a collection-oriented
eager loader that is superior in most respects to :func:`_orm.joinedload`
and should be preferred.
+.. _migration_20_dynamic_loaders:
+
+Making use of "dynamic" relationship loads without using Query
+---------------------------------------------------------------
+
+**Synopsis**
+
+The ``lazy="dynamic"`` relationship loader strategy, discussed at
+:ref:`dynamic_relationship`, makes use of the :class:`_query.Query` object
+which is legacy in 2.0.
+
+
+**Migration to 2.0**
+
+This pattern is still under adjustment for SQLAlchemy 2.0, and it is expected
+that new APIs will be introduced. In the interim, there are two ways
+to achieve 2.0 style querying that's in terms of a specific relationship:
+
+* Make use of the :attr:`_orm.Query.statement` attribute on an existing
+ ``lazy="dynamic"`` relationship. We can use methods like
+ :meth:`_orm.Session.scalars` with the dynamic loader straight away as
+ follows::
+
+
+ class User(Base):
+ __tablename__ = 'user'
+
+ posts = relationship(Post, lazy="dynamic")
+
+ jack = session.get(User, 5)
+
+ # filter Jack's blog posts
+ posts = session.scalars(
+ jack.posts.statement.where(Post.headline == "this is a post")
+ )
+
+* Use the :func:`_orm.with_parent` function to construct a :func:`_sql.select`
+ construct directly::
+
+ from sqlalchemy.orm import with_parent
+
+ jack = session.get(User, 5)
+
+ posts = session.scalars(
+ select(Post).
+ where(with_parent(jack, User.posts)).
+ where(Post.headline == "this is a post")
+ )
+
+**Discussion**
+
+The original idea was that the :func:`_orm.with_parent` function should be
+sufficient, however continuing to make use of special attributes on the
+relationship itself remains appealing, and there's no reason a 2.0 style
+construct can't be made to work here as well. There will likely be a new
+loader strategy name that sets up an API similar to the example above that
+uses the ``.statement`` attribute, such as
+``jack.posts.select().where(Post.headline == 'headline')``.
+
.. _migration_20_session_autocommit:
Autocommit mode removed from Session; autobegin support added
diff --git a/doc/build/orm/collections.rst b/doc/build/orm/collections.rst
index a811779af..964089197 100644
--- a/doc/build/orm/collections.rst
+++ b/doc/build/orm/collections.rst
@@ -32,10 +32,10 @@ loading of child items both at load time as well as deletion time.
Dynamic Relationship Loaders
----------------------------
-.. note:: This is a legacy feature. Using the :func:`_orm.with_parent`
- filter in conjunction with :func:`_sql.select` is the :term:`2.0 style`
- method of use. For relationships that shouldn't load, set
- :paramref:`_orm.relationship.lazy` to ``noload``.
+.. note:: SQLAlchemy 2.0 will have a slightly altered pattern for "dynamic"
+ loaders that does not rely upon the :class:`_orm.Query` object, which
+ will be legacy in 2.0. For current migration strategies,
+ see :ref:`migration_20_dynamic_loaders`.
.. note:: This loader is in the general case not compatible with the :ref:`asyncio_toplevel` extension.
It can be used with some limitations, as indicated in :ref:`Asyncio dynamic guidelines <dynamic_asyncio>`.
diff --git a/doc/build/orm/extensions/asyncio.rst b/doc/build/orm/extensions/asyncio.rst
index fcaf10446..91c7c53e1 100644
--- a/doc/build/orm/extensions/asyncio.rst
+++ b/doc/build/orm/extensions/asyncio.rst
@@ -343,6 +343,10 @@ Other guidelines include:
)
addresses_filter = (await session.scalars(stmt)).all()
+ .. seealso::
+
+ :ref:`migration_20_dynamic_loaders` - notes on migration to 2.0 style
+
.. _session_run_sync:
Running Synchronous Methods and Functions under asyncio
diff --git a/doc/build/orm/queryguide.rst b/doc/build/orm/queryguide.rst
index a5b8813df..f2839547f 100644
--- a/doc/build/orm/queryguide.rst
+++ b/doc/build/orm/queryguide.rst
@@ -1116,9 +1116,9 @@ Additional ORM API Constructs
.. autofunction:: sqlalchemy.orm.with_loader_criteria
-.. autofunction:: join
+.. autofunction:: sqlalchemy.orm.join
-.. autofunction:: outerjoin
+.. autofunction:: sqlalchemy.orm.outerjoin
-.. autofunction:: with_parent
+.. autofunction:: sqlalchemy.orm.with_parent