summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-06-10 23:53:05 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2015-06-10 23:53:05 -0400
commitfe6827b88837b264f726e17891eb37e2b7e38a83 (patch)
tree0492dd6ef4ef80d1a5751484912a087795357606
parentee79d879e4800d0abf7abcd594c37b1cd833ac91 (diff)
downloadsqlalchemy-ticket_1311.tar.gz
- add some more detailticket_1311
-rw-r--r--examples/custom_attributes/active_column_defaults.py35
1 files changed, 28 insertions, 7 deletions
diff --git a/examples/custom_attributes/active_column_defaults.py b/examples/custom_attributes/active_column_defaults.py
index 5f2d7b749..9560c3dc0 100644
--- a/examples/custom_attributes/active_column_defaults.py
+++ b/examples/custom_attributes/active_column_defaults.py
@@ -5,8 +5,15 @@ def configure_listener(mapper, class_):
"""Establish attribute setters for every default-holding column on the
given mapper."""
+ # iterate through ColumnProperty objects
for col_attr in mapper.column_attrs:
+
+ # look at the Column mapped by the ColumnProperty
+ # (we look at the first column in the less common case
+ # of a property mapped to multiple columns at once)
column = col_attr.columns[0]
+
+ # if the Column has a "default", set up a listener
if column.default is not None:
default_listener(col_attr, column.default)
@@ -14,7 +21,11 @@ def configure_listener(mapper, class_):
def default_listener(col_attr, default):
"""Establish a default-setting listener.
- Given a class_, attrname, and a :class:`.ColumnDefault` instance.
+ Given a class_, attrname, and a :class:`.DefaultGenerator` instance.
+ The default generator should be a :class:`.ColumnDefault` object with a
+ plain Python value or callable default; otherwise, the appropriate behavior
+ for SQL functions and defaults should be determined here by the
+ user integrating this feature.
"""
@event.listens_for(col_attr, "init_scalar", retval=True, propagate=True)
@@ -24,17 +35,24 @@ def default_listener(col_attr, default):
# the callable of ColumnDefault always accepts a context
# argument; we can pass it as None here.
value = default.arg(None)
- elif default.is_clause_element or default.is_sequence:
- # the feature can't easily support this. This
+ elif default.is_scalar:
+ value = default.arg
+ else:
+ # default is a Sequence, a SQL expression, server
+ # side default generator, or other non-Python-evaluable
+ # object. The feature here can't easily support this. This
# can be made to return None, rather than raising,
# or can procure a connection from an Engine
# or Session and actually run the SQL, if desired.
raise NotImplementedError(
"Can't invoke pre-default for a SQL-level column default")
- else:
- value = default.arg
+ # set the value in the given dict_; this won't emit any further
+ # attribute set events or create attribute "history", but the value
+ # will be used in the INSERT statement
dict_[col_attr.key] = value
+
+ # return the value as well
return value
@@ -44,6 +62,7 @@ if __name__ == '__main__':
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base
import datetime
+ import time
Base = declarative_base()
@@ -62,7 +81,8 @@ if __name__ == '__main__':
w1 = Widget()
- # not persisted at all, default values are present
+ # not persisted at all, default values are present the moment
+ # we access them
assert w1.radius == 30
current_time = w1.timestamp
assert (
@@ -74,7 +94,8 @@ if __name__ == '__main__':
sess.add(w1)
sess.commit()
- # data is persisted
+ # data is persisted. The timestamp is also the one we generated above;
+ # e.g. the default wasn't re-invoked later.
assert (
sess.query(Widget.radius, Widget.timestamp).first() ==
(30, current_time)