summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/__init__.py1
-rw-r--r--lib/sqlalchemy/orm/relationships.py8
-rw-r--r--lib/sqlalchemy/orm/strategies.py27
-rw-r--r--lib/sqlalchemy/orm/strategy_options.py29
4 files changed, 65 insertions, 0 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index 7425737ce..d822c83cb 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -242,6 +242,7 @@ subqueryload = strategy_options.subqueryload._unbound_fn
subqueryload_all = strategy_options.subqueryload_all._unbound_all_fn
immediateload = strategy_options.immediateload._unbound_fn
noload = strategy_options.noload._unbound_fn
+raiseload = strategy_options.raiseload._unbound_fn
defaultload = strategy_options.defaultload._unbound_fn
from .strategy_options import Load
diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py
index 17f94d4af..4d5e5d29d 100644
--- a/lib/sqlalchemy/orm/relationships.py
+++ b/lib/sqlalchemy/orm/relationships.py
@@ -540,6 +540,12 @@ class RelationshipProperty(StrategizedProperty):
support "write-only" attributes, or attributes which are
populated in some manner specific to the application.
+ * ``raise`` - lazy loading is disallowed; accessing
+ the attribute, if its value were not already loaded via eager
+ loading, will raise an :exc:`~sqlalchemy.exc.InvalidRequestError`.
+
+ .. versionadded:: 1.1
+
* ``dynamic`` - the attribute will return a pre-configured
:class:`.Query` object for all read
operations, onto which further filtering operations can be
@@ -559,6 +565,8 @@ class RelationshipProperty(StrategizedProperty):
:ref:`dynamic_relationship` - detail on the ``dynamic`` option.
+ :ref:`collections_noload_raiseload` - notes on "noload" and "raise"
+
:param load_on_pending=False:
Indicates loading behavior for transient or pending parent objects.
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 370cb974b..3c03a681d 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -354,6 +354,33 @@ class NoLoader(AbstractRelationshipLoader):
@log.class_logger
+@properties.RelationshipProperty.strategy_for(lazy="raise")
+class RaiseLoader(NoLoader):
+ """Provide loading behavior for a :class:`.RelationshipProperty`
+ with "lazy='raise'".
+
+ """
+
+ __slots__ = ()
+
+ def create_row_processor(
+ self, context, path, loadopt, mapper,
+ result, adapter, populators):
+
+ def invoke_raise_load(state, passive):
+ raise sa_exc.InvalidRequestError(
+ "'%s' is not available due to lazy='raise'" % self
+ )
+
+ set_lazy_callable = InstanceState._instance_level_callable_processor(
+ mapper.class_manager,
+ invoke_raise_load,
+ self.key
+ )
+ populators["new"].append((self.key, set_lazy_callable))
+
+
+@log.class_logger
@properties.RelationshipProperty.strategy_for(lazy=True)
@properties.RelationshipProperty.strategy_for(lazy="select")
class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py
index b7084cc22..97d2c0f29 100644
--- a/lib/sqlalchemy/orm/strategy_options.py
+++ b/lib/sqlalchemy/orm/strategy_options.py
@@ -879,6 +879,35 @@ def noload(*keys):
@loader_option()
+def raiseload(loadopt, attr):
+ """Indicate that the given relationship attribute should disallow lazy loads.
+
+ A relationship attribute configured with :func:`.orm.raiseload` will
+ raise an :exc:`~sqlalchemy.exc.InvalidRequestError` upon access. The
+ typical way this is useful is when an application is attempting to ensure
+ that all relationship attributes that are accessed in a particular context
+ would have been already loaded via eager loading. Instead of having
+ to read through SQL logs to ensure lazy loads aren't occurring, this
+ strategy will cause them to raise immediately.
+
+ This function is part of the :class:`.Load` interface and supports
+ both method-chained and standalone operation.
+
+ :func:`.orm.raiseload` applies to :func:`.relationship` attributes only.
+
+ .. versionadded:: 1.1
+
+ """
+
+ return loadopt.set_relationship_strategy(attr, {"lazy": "raise"})
+
+
+@raiseload._add_unbound_fn
+def raiseload(*keys):
+ return _UnboundLoad._from_keys(_UnboundLoad.raiseload, keys, False, {})
+
+
+@loader_option()
def defaultload(loadopt, attr):
"""Indicate an attribute should load using its default loader style.