summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/orm/constructors.rst30
-rw-r--r--lib/sqlalchemy/orm/events.py5
-rw-r--r--lib/sqlalchemy/orm/mapper.py6
3 files changed, 28 insertions, 13 deletions
diff --git a/doc/build/orm/constructors.rst b/doc/build/orm/constructors.rst
index 637afccb7..4d7268557 100644
--- a/doc/build/orm/constructors.rst
+++ b/doc/build/orm/constructors.rst
@@ -18,10 +18,13 @@ then quietly restoring attributes directly on the instance rather than calling
``__init__``.
If you need to do some setup on database-loaded instances before they're ready
-to use, you can use the ``@reconstructor`` decorator to tag a method as the
-ORM counterpart to ``__init__``. SQLAlchemy will call this method with no
-arguments every time it loads or reconstructs one of your instances. This is
-useful for recreating transient properties that are normally assigned in your
+to use, there is an event hook known as :meth:`.InstanceEvents.load` which
+can achieve this; it is also available via a class-specific decorator called
+:func:`.orm.reconstructor`. When using :func:`.orm.reconstructor`,
+the mapper will invoke the decorated method with no
+arguments every time it loads or reconstructs an instance of the
+class. This is
+useful for recreating transient properties that are normally assigned in
``__init__``::
from sqlalchemy import orm
@@ -36,21 +39,22 @@ useful for recreating transient properties that are normally assigned in your
def init_on_load(self):
self.stuff = []
-When ``obj = MyMappedClass()`` is executed, Python calls the ``__init__``
-method as normal and the ``data`` argument is required. When instances are
+Above, when ``obj = MyMappedClass()`` is executed, the ``__init__`` constructor
+is invoked normally and the ``data`` argument is required. When instances are
loaded during a :class:`~sqlalchemy.orm.query.Query` operation as in
``query(MyMappedClass).one()``, ``init_on_load`` is called.
-Any method may be tagged as the :func:`~sqlalchemy.orm.reconstructor`, even
-the ``__init__`` method. SQLAlchemy will call the reconstructor method with no
-arguments. Scalar (non-collection) database-mapped attributes of the instance
-will be available for use within the function. Eagerly-loaded collections are
-generally not yet available and will usually only contain the first element.
+Any method may be tagged as the :func:`.orm.reconstructor`, even
+the ``__init__`` method itself. It is invoked after all immediate
+column-level attributes are loaded as well as after eagerly-loaded scalar
+relationships. Eagerly loaded collections may be only partially populated
+or not populated at all, depending on the kind of eager loading used.
+
ORM state changes made to objects at this stage will not be recorded for the
-next flush() operation, so the activity within a reconstructor should be
+next flush operation, so the activity within a reconstructor should be
conservative.
-:func:`~sqlalchemy.orm.reconstructor` is a shortcut into a larger system
+:func:`.orm.reconstructor` is a shortcut into a larger system
of "instance level" events, which can be subscribed to using the
event API - see :class:`.InstanceEvents` for the full API description
of these events.
diff --git a/lib/sqlalchemy/orm/events.py b/lib/sqlalchemy/orm/events.py
index d2ccec432..9e67da5bc 100644
--- a/lib/sqlalchemy/orm/events.py
+++ b/lib/sqlalchemy/orm/events.py
@@ -302,6 +302,9 @@ class InstanceEvents(event.Events):
attributes and collections may or may not be loaded or even
initialized, depending on what's present in the result rows.
+ The :meth:`.InstanceEvents.load` event is also available in a
+ class-method decorator format called :func:`.orm.reconstructor`.
+
:param target: the mapped instance. If
the event is configured with ``raw=True``, this will
instead be the :class:`.InstanceState` state-management
@@ -319,6 +322,8 @@ class InstanceEvents(event.Events):
:meth:`.SessionEvents.loaded_as_persistent`
+ :ref:`mapping_constructors`
+
"""
def refresh(self, target, context, attrs):
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 3f0c866d1..83f8eca1c 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -2902,6 +2902,12 @@ def reconstructor(fn):
this stage will not be recorded for the next flush() operation, so
the activity within a reconstructor should be conservative.
+ .. seealso::
+
+ :ref:`mapping_constructors`
+
+ :meth:`.InstanceEvents.load`
+
"""
fn.__sa_reconstructor__ = True
return fn