From 63508b82cd5710c660383bcac5fcfd3bb6af83c1 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 19 Nov 2013 19:16:26 -0500 Subject: - The ``viewonly`` flag on :func:`.relationship` will now prevent attribute history from being written on behalf of the target attribute. This has the effect of the object not being written to the Session.dirty list if it is mutated. Previously, the object would be present in Session.dirty, but no change would take place on behalf of the modified attribute during flush. The attribute still emits events such as backref events and user-defined events and will still receive mutations from backrefs. [ticket:2833] --- lib/sqlalchemy/orm/attributes.py | 6 ++++++ lib/sqlalchemy/orm/state.py | 2 ++ lib/sqlalchemy/orm/strategies.py | 1 + 3 files changed, 9 insertions(+) (limited to 'lib/sqlalchemy/orm') diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index e78973459..6071b565d 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -370,6 +370,7 @@ class AttributeImpl(object): callable_, dispatch, trackparent=False, extension=None, compare_function=None, active_history=False, parent_token=None, expire_missing=True, + send_modified_events=True, **kwargs): """Construct an AttributeImpl. @@ -413,6 +414,10 @@ class AttributeImpl(object): during state.expire_attributes(None), if no value is present for this key. + send_modified_events + if False, the InstanceState._modified_event method will have no effect; + this means the attribute will never show up as changed in a + history entry. """ self.class_ = class_ self.key = key @@ -420,6 +425,7 @@ class AttributeImpl(object): self.dispatch = dispatch self.trackparent = trackparent self.parent_token = parent_token or self + self.send_modified_events = send_modified_events if compare_function is None: self.is_equal = operator.eq else: diff --git a/lib/sqlalchemy/orm/state.py b/lib/sqlalchemy/orm/state.py index 957e29700..ddd991acc 100644 --- a/lib/sqlalchemy/orm/state.py +++ b/lib/sqlalchemy/orm/state.py @@ -415,6 +415,8 @@ class InstanceState(interfaces._InspectionAttr): return None def _modified_event(self, dict_, attr, previous, collection=False): + if not attr.send_modified_events: + return if attr.key not in self.committed_state: if collection: if previous is NEVER_SET: diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 009bf74a4..b04338d9c 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -80,6 +80,7 @@ def _register_attribute(strategy, mapper, useobject, callable_=callable_, active_history=active_history, impl_class=impl_class, + send_modified_events=not useobject or not prop.viewonly, doc=prop.doc, **kw ) -- cgit v1.2.1