diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-05-17 15:48:39 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-05-17 15:48:39 -0400 |
| commit | 93b29aefdcaa736cd180ab3ae31168163e9f0212 (patch) | |
| tree | 0a47139b16558da859fd78e165ca01a5d6a6dade /lib/sqlalchemy | |
| parent | d05319ec7e7868fb09792d07d975c029c178d2d0 (diff) | |
| download | sqlalchemy-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__.py | 15 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 1 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/session.py | 44 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/state.py | 1 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 6 |
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 |
