From: Mike Bayer Date: Tue, 19 Nov 2019 15:12:35 +0000 (-0500) Subject: Use viewonly=True for composite secondary join example X-Git-Tag: rel_1_3_12~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4ce99274ac13894e38e4d12a4103637651c14b59;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Use viewonly=True for composite secondary join example This example isn't writable as given. Add additonal warnings. Also modernize the "query-enabled property" section and add links to hybrids. Fixes: #4992 Change-Id: I8f4b4db9e42ab2207a74532e3b17a56c35b0a837 (cherry picked from commit 25a6596030cbf16a870db142ddf096223c79be7a) --- diff --git a/doc/build/orm/join_conditions.rst b/doc/build/orm/join_conditions.rst index ef33d30a73..ef023feb47 100644 --- a/doc/build/orm/join_conditions.rst +++ b/doc/build/orm/join_conditions.rst @@ -600,7 +600,10 @@ Composite "Secondary" Joins .. note:: - This section features some new and experimental features of SQLAlchemy. + This section features far edge cases that are somewhat supported + by SQLAlchemy, however it is recommended to solve problems like these + in simpler ways whenever possible, by using reasonable relational + layouts and / or :ref:`in-Python attributes `. Sometimes, when one seeks to build a :func:`.relationship` between two tables there is a need for more than just two or three tables to be involved in @@ -625,7 +628,8 @@ join condition (requires version 0.9.2 at least to function as is):: "join(C, C.d_id == D.id)", primaryjoin="and_(A.b_id == B.id, A.id == C.a_id)", secondaryjoin="D.id == B.d_id", - uselist=False + uselist=False, + viewonly=True ) class B(Base): @@ -667,11 +671,10 @@ tables while still keeping things "simple" for :func:`.relationship`, in that there's just "one" table on both the "left" and the "right" side; the complexity is kept within the middle. -.. versionadded:: 0.9.2 Support is improved for allowing a :func:`.join()` - construct to be used directly as the target of the :paramref:`~.relationship.secondary` - argument, including support for joins, eager joins and lazy loading, - as well as support within declarative to specify complex conditions such - as joins involving class names as targets. +.. warning:: A relationship like the above is typically marked as + ``viewonly=True`` and should be considered as read-only. While there are + sometimes ways to make relationships like the above writable, this is + generally complicated and error prone. .. _relationship_aliased_class: @@ -822,6 +825,7 @@ Such a mapping would ordinarily also include a "plain" relationship from "A" to "B", for persistence operations as well as when the full set of "B" objects per "A" is desired. +.. _query_enabled_properties: Building Query-Enabled Properties ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -840,7 +844,14 @@ conjunction with :class:`.Query` as follows: __tablename__ = 'user' id = Column(Integer, primary_key=True) - def _get_addresses(self): + @property + def addresses(self): return object_session(self).query(Address).with_parent(self).filter(...).all() - addresses = property(_get_addresses) +In other cases, the descriptor can be built to make use of existing in-Python +data. See the section on :ref:`mapper_hybrids` for more general discussion +of special Python attributes. + +.. seealso:: + + :ref:`mapper_hybrids` \ No newline at end of file