]> 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:32:12 +0000 (14:32 -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
(cherry picked from commit 29c5fba9ad89e53180f0bd2a026742321093105f)

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

index 79e198d09c4b47a684b9f42dcfc40948f1fcb263..8f35220d890c6fc66560ce6bfe256a8d2c307e68 100644 (file)
@@ -260,12 +260,12 @@ the SQLAlchemy project itself, the approach taken is as follows:
 
         import warnings
         from sqlalchemy import exc
-        
+
         # for warnings not included in regex-based filter below, just log
         warnings.filterwarnings(
           "always", category=exc.RemovedIn20Warning
         )
-        
+
         # for warnings related to execute() / scalar(), raise
         for msg in [
             r"The (?:Executable|Engine)\.(?:execute|scalar)\(\) function",
@@ -1966,6 +1966,66 @@ 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 bc98b4b41d810b60cfe28679c24474046451fae4..31db0b261687a017415d14bd8907032358971ef4 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 a10af53ba14a673ac114612c65c387625d65ce27..91c0b311980379b57da839c4371c6b5daa0ba5e8 100644 (file)
@@ -1081,4 +1081,4 @@ matching objects locally present in the :class:`_orm.Session`. See the section
 ..  Setup code, not for display
 
     >>> conn.close()
-    ROLLBACK
\ No newline at end of file
+    ROLLBACK