summaryrefslogtreecommitdiff
path: root/doc/build
diff options
context:
space:
mode:
authorFederico Caselli <cfederico87@gmail.com>2023-04-28 22:26:41 +0200
committerFederico Caselli <cfederico87@gmail.com>2023-04-28 22:26:41 +0200
commitb19a69d7cfd7b00d4c850dd2ef55a765c7496e77 (patch)
tree29c8724dcc1f71e54c3d7c229a422948fe3be862 /doc/build
parent39c8e95b1f50190ff30a836b2bcf13ba2cacc052 (diff)
downloadsqlalchemy-b19a69d7cfd7b00d4c850dd2ef55a765c7496e77.tar.gz
Add scalar example in association proxy examples
Fixes: #9699 Change-Id: I73f800b9b3676cbf0ac04534c0ca4e40f23bf0ec
Diffstat (limited to 'doc/build')
-rw-r--r--doc/build/orm/extensions/associationproxy.rst79
1 files changed, 75 insertions, 4 deletions
diff --git a/doc/build/orm/extensions/associationproxy.rst b/doc/build/orm/extensions/associationproxy.rst
index 036969f37..7b1ae3399 100644
--- a/doc/build/orm/extensions/associationproxy.rst
+++ b/doc/build/orm/extensions/associationproxy.rst
@@ -8,13 +8,18 @@ Association Proxy
``associationproxy`` is used to create a read/write view of a
target attribute across a relationship. It essentially conceals
the usage of a "middle" attribute between two endpoints, and
-can be used to cherry-pick fields from a collection of
-related objects or to reduce the verbosity of using the association
-object pattern. Applied creatively, the association proxy allows
+can be used to cherry-pick fields from both a collection of
+related objects or scalar relationship. or to reduce the verbosity
+of using the association object pattern.
+Applied creatively, the association proxy allows
the construction of sophisticated collections and dictionary
views of virtually any geometry, persisted to the database using
standard, transparently configured relational patterns.
+.. contents:: Some example use cases for Association Proxy
+ :depth: 1
+ :local:
+
.. _associationproxy_scalar_collections:
Simplifying Scalar Collections
@@ -124,7 +129,7 @@ the underlying collection or attribute does.
.. _associationproxy_creator:
Creation of New Values
-----------------------
+^^^^^^^^^^^^^^^^^^^^^^
When a list ``append()`` event (or set ``add()``, dictionary ``__setitem__()``,
or scalar assignment event) is intercepted by the association proxy, it
@@ -689,6 +694,72 @@ deleted depends on the relationship cascade setting.
:ref:`unitofwork_cascades`
+Scalar Relationships
+--------------------
+
+The example below illustrates the use of the association proxy on the many
+side of of a one-to-many relationship, accessing attributes of a scalar
+object::
+
+ from __future__ import annotations
+
+ from typing import List
+
+ from sqlalchemy import ForeignKey
+ from sqlalchemy import String
+ from sqlalchemy.ext.associationproxy import association_proxy
+ from sqlalchemy.ext.associationproxy import AssociationProxy
+ from sqlalchemy.orm import DeclarativeBase
+ from sqlalchemy.orm import Mapped
+ from sqlalchemy.orm import mapped_column
+ from sqlalchemy.orm import relationship
+
+
+ class Base(DeclarativeBase):
+ pass
+
+
+ class Recipe(Base):
+ __tablename__ = "recipe"
+ id: Mapped[int] = mapped_column(primary_key=True)
+ name: Mapped[str] = mapped_column(String(64))
+
+ steps: Mapped[List[Step]] = relationship(back_populates="recipe")
+ step_descriptions: AssociationProxy[List[str]] = association_proxy(
+ "steps", "description"
+ )
+
+
+ class Step(Base):
+ __tablename__ = "step"
+ id: Mapped[int] = mapped_column(primary_key=True)
+ description: Mapped[str]
+ recipe_id: Mapped[int] = mapped_column(ForeignKey("recipe.id"))
+ recipe: Mapped[Recipe] = relationship(back_populates="steps")
+
+ recipe_name: AssociationProxy[str] = association_proxy("recipe", "name")
+
+ def __init__(self, description: str) -> None:
+ self.description = description
+
+
+ my_snack = Recipe(
+ name="afternoon snack",
+ step_descriptions=[
+ "slice bread",
+ "spread peanut butted",
+ "eat sandwich",
+ ],
+ )
+
+A summary of the steps of ``my_snack`` can be printed using::
+
+ >>> for i, step in enumerate(my_snack.steps, 1):
+ ... print(f"Step {i} of {step.recipe_name!r}: {step.description}")
+ Step 1 of 'afternoon snack': slice bread
+ Step 2 of 'afternoon snack': spread peanut butted
+ Step 3 of 'afternoon snack': eat sandwich
+
API Documentation
-----------------