diff options
Diffstat (limited to 'lib/sqlalchemy/orm')
| -rw-r--r-- | lib/sqlalchemy/orm/__init__.py | 1 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/relationships.py | 8 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 27 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategy_options.py | 29 |
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. |
