diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-12-26 17:28:56 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-12-26 17:28:56 -0500 |
| commit | 2e58059cbba6f612a86a9d03583e30717bcdd6c4 (patch) | |
| tree | 10531fcd8c63da1426b19087775f89de023ef1c1 /examples | |
| parent | 7dbb6bffc20bccb6e7087f9cfddb8463d9178204 (diff) | |
| download | sqlalchemy-2e58059cbba6f612a86a9d03583e30717bcdd6c4.tar.gz | |
- docs for mutable events example
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/mutable_events/__init__.py | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/examples/mutable_events/__init__.py b/examples/mutable_events/__init__.py index 813dc5abd..3b6363b96 100644 --- a/examples/mutable_events/__init__.py +++ b/examples/mutable_events/__init__.py @@ -1,14 +1,36 @@ """ Illustrates how to build and use "mutable" types, such as dictionaries and user-defined classes, as scalar attributes which detect in-place changes. +These types don't make use of the "mutable=True" flag, which +performs poorly within the ORM and is being phased out, instead allowing +changes on data to associate change events with the parent object +as they happen in the same way as any other mapped data member. The example is based around the usage of the event model introduced in -:ref:`event_toplevel`, along with the :func:`attributes.flag_modified` function +:ref:`event_toplevel`, along with the :func:`~.attributes.flag_modified` function which establishes the "dirty" flag on a particular mapped attribute. These functions are encapsulated in a mixin called ``TrackMutationsMixin``. -Subclassing ``dict`` to provide "mutation tracking" looks like:: +Subclassing ``dict`` to provide "mutation tracking", then +applying it to a custom dictionary type, looks like:: + + class JSONEncodedDict(TypeDecorator): + "JSON dictionary type from the types documentation" + + impl = VARCHAR + + def process_bind_param(self, value, dialect): + if value is not None: + value = simplejson.dumps(value, use_decimal=True) + return value + + def process_result_value(self, value, dialect): + if value is not None: + value = simplejson.loads(value, use_decimal=True) + return value class MutationDict(TrackMutationsMixin, dict): + "Subclass dict to send mutation events to the owning object." + def __init__(self, other): self.update(other) @@ -20,17 +42,21 @@ Subclassing ``dict`` to provide "mutation tracking" looks like:: dict.__delitem__(self, key) self.on_change() + # hypothetical mapping Base = declarative_base() class Foo(Base): __tablename__ = 'foo' id = Column(Integer, primary_key=True) data = Column(JSONEncodedDict) + # add mutation tracking to `Foo.data` as a one off MutationDict.associate_with_attribute(Foo.data) The explicit step of associating ``MutationDict`` with ``Foo.data`` can be automated across a class of columns using ``associate_with_type()``:: + # add mutation tracking to all mapped attributes + # that use JSONEncodedDict MutationDict.associate_with_type(JSONEncodedDict) All subsequent mappings will have the ``MutationDict`` wrapper applied to |
