diff --git a/sqlalchemy_utils/listeners.py b/sqlalchemy_utils/listeners.py index 243e35b..9783183 100644 --- a/sqlalchemy_utils/listeners.py +++ b/sqlalchemy_utils/listeners.py @@ -17,3 +17,20 @@ def coercion_listener(mapper, class_): listener, retval=True ) + + +def instant_defaults_listener(target, args, kwargs): + for key, column in sa.inspect(target.__class__).columns.items(): + if column.default is not None: + if callable(column.default.arg): + setattr(target, key, column.default.arg(target)) + else: + setattr(target, key, column.default.arg) + + +def coerce_data_types(mapper=sa.orm.mapper): + sa.event.listen(mapper, 'mapper_configured', coercion_listener) + + +def force_instant_defaults(mapper=sa.orm.mapper): + sa.event.listen(mapper, 'init', instant_defaults_listener) diff --git a/tests/test_instant_defaults_listener.py b/tests/test_instant_defaults_listener.py new file mode 100644 index 0000000..fa1a2d4 --- /dev/null +++ b/tests/test_instant_defaults_listener.py @@ -0,0 +1,26 @@ +from datetime import datetime +import sqlalchemy as sa +from sqlalchemy_utils.listeners import force_instant_defaults +from tests import TestCase + + +force_instant_defaults() + + +class TestInstantDefaultListener(TestCase): + def create_models(self): + class Article(self.Base): + __tablename__ = 'article' + id = sa.Column(sa.Integer, primary_key=True) + name = sa.Column(sa.Unicode(255), default=u'Some article') + created_at = sa.Column(sa.DateTime, default=datetime.now) + + self.Article = Article + + def test_assigns_defaults_on_object_construction(self): + article = self.Article() + assert article.name == u'Some article' + + def test_callables_as_defaults(self): + article = self.Article() + assert isinstance(article.created_at, datetime)