]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
update migration strategy for dynamic loaders
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 27 Nov 2021 19:29:00 +0000 (14:29 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 27 Nov 2021 19:30:56 +0000 (14:30 -0500)
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

doc/build/changelog/migration_20.rst
doc/build/orm/collections.rst
doc/build/orm/extensions/asyncio.rst
doc/build/orm/queryguide.rst

index 1c01698886154e8834e4f21149a984ef9f685926..5fdd093d0b7ec94e9a2fe285076e8d998a22f694 100644 (file)
@@ -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
index a811779afa707198f20f9830f425285fdc409532..96408919762e390385dca75c3330e22113be6e29 100644 (file)
@@ -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>`.
index fcaf104467cf3b1e9ca0ae5764012672fb26e4c5..91c7c53e1e9031c8e98523a8261521fc9d2dddda 100644 (file)
@@ -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
index a5b8813df9cbd575f85c805a1bcb1fd130d4829d..f2839547fb532c88d07e5722e0424ad111fb6630 100644 (file)
@@ -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