summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-05-17 15:48:39 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2012-05-17 15:48:39 -0400
commit93b29aefdcaa736cd180ab3ae31168163e9f0212 (patch)
tree0a47139b16558da859fd78e165ca01a5d6a6dade /lib/sqlalchemy
parentd05319ec7e7868fb09792d07d975c029c178d2d0 (diff)
downloadsqlalchemy-93b29aefdcaa736cd180ab3ae31168163e9f0212.tar.gz
- [feature] Added utility feature
Session.enable_relationship_loading(), supersedes relationship.load_on_pending. Both features should be avoided, however. [ticket:2372]
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/__init__.py15
-rw-r--r--lib/sqlalchemy/orm/attributes.py1
-rw-r--r--lib/sqlalchemy/orm/session.py44
-rw-r--r--lib/sqlalchemy/orm/state.py1
-rw-r--r--lib/sqlalchemy/orm/strategies.py6
5 files changed, 55 insertions, 12 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index bc3523fe2..daa843dc5 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -465,20 +465,17 @@ def relationship(argument, secondary=None, **kwargs):
:param load_on_pending=False:
Indicates loading behavior for transient or pending parent objects.
+
+ .. note::
+
+ load_on_pending is superseded by :meth:`.Session.enable_relationship_loading`.
When set to ``True``, causes the lazy-loader to
issue a query for a parent object that is not persistent, meaning it has
never been flushed. This may take effect for a pending object when
autoflush is disabled, or for a transient object that has been
"attached" to a :class:`.Session` but is not part of its pending
- collection. Attachment of transient objects to the session without
- moving to the "pending" state is not a supported behavior at this time.
-
- Note that the load of related objects on a pending or transient object
- also does not trigger any attribute change events - no user-defined
- events will be emitted for these attributes, and if and when the
- object is ultimately flushed, only the user-specific foreign key
- attributes will be part of the modified state.
+ collection.
The load_on_pending flag does not improve behavior
when the ORM is used normally - object references should be constructed
@@ -486,7 +483,7 @@ def relationship(argument, secondary=None, **kwargs):
are present in an ordinary way before flush() proceeds. This flag
is not not intended for general use.
- New in 0.6.5.
+ .. versionadded:: 0.6.5
:param order_by:
indicates the ordering that should be applied when loading these
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index 00d640066..55e0291b5 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -817,7 +817,6 @@ class CollectionAttributeImpl(AttributeImpl):
def append(self, state, dict_, value, initiator, passive=PASSIVE_OFF):
if initiator and initiator.parent_token is self.parent_token:
return
-
collection = self.get_collection(state, dict_, passive=passive)
if collection is PASSIVE_NO_RESULT:
value = self.fire_append_event(state, dict_, value, initiator)
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index eb15e033e..40e4375ed 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -1514,6 +1514,50 @@ class Session(object):
self._deleted[state] = state.obj()
self.identity_map.add(state)
+ def enable_relationship_loading(self, obj):
+ """Associate an object with this :class:`.Session` for related
+ object loading.
+
+ Accesses of attributes mapped with :class:`.relationship`
+ will attempt to load a value from the database using this
+ :class:`.Session` as the source of connectivity. The values
+ will be loaded based on foreign key values present on this
+ object - it follows that this functionality
+ generally only works for many-to-one-relationships.
+
+ The object will be attached to this session, but will
+ ''not'' participate in any persistence operations; its state
+ for almost all purposes will remain either "transient" or
+ "detached", except for the case of relationship loading.
+
+ Also note that backrefs will often not work as expected.
+ Altering a relationship-bound attribute on the target object
+ may not fire off a backref event, if the effective value
+ is what was already loaded from a foreign-key-holding value.
+
+ The :meth:`.Session.enable_relationship_loading` method supersedes
+ the ``load_on_pending`` flag on :func:`.relationship`. Unlike
+ that flag, :meth:`.Session.enable_relationship_loading` allows
+ an object to remain transient while still being able to load
+ related items.
+
+ To make a transient object associated with a :class:`.Session`
+ via :meth:`.Session.enable_relationship_loading` pending, add
+ it to the :class:`.Session` using :meth:`.Session.add` normally.
+
+ :meth:`.Session.enable_relationship_loading` does not improve
+ behavior when the ORM is used normally - object references should be constructed
+ at the object level, not at the foreign key level, so that they
+ are present in an ordinary way before flush() proceeds. This method
+ is not intended for general use.
+
+ .. versionadded:: 0.8
+
+ """
+ state = attributes.instance_state(obj)
+ self._attach(state)
+ state._load_pending = True
+
def _attach(self, state):
if state.key and \
state.key in self.identity_map and \
diff --git a/lib/sqlalchemy/orm/state.py b/lib/sqlalchemy/orm/state.py
index bb6104762..9b0f7538f 100644
--- a/lib/sqlalchemy/orm/state.py
+++ b/lib/sqlalchemy/orm/state.py
@@ -37,6 +37,7 @@ class InstanceState(object):
modified = False
expired = False
deleted = False
+ _load_pending = False
def __init__(self, obj, manager):
self.class_ = obj.__class__
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index a9a73cd66..e1f838793 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -448,8 +448,10 @@ class LazyLoader(AbstractRelationshipLoader):
return criterion
def _load_for_state(self, state, passive):
- if not state.key and \
- (not self.parent_property.load_on_pending or not state.session_id):
+ if not state.session_id or \
+ not state.key and \
+ not self.parent_property.load_on_pending and \
+ not state._load_pending:
return attributes.ATTR_EMPTY
pending = not state.key