我正在尝试同时处理两件新事物,因此我们非常感谢您在简化和澄清方面的帮助。
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy import Column, Float, event
class TimeStampMixin(object):
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
created = Column(Float)
modified = Column(Float)
def __init__(self, created = None,
modified = None):
self.created = created
self.modified = modified
def create_time(mapper, connection, target):
target.created = time()
#def modified_time(mapper, connection, target):
# target.modified = time()
event.listen(TimeStampMixin, 'before_insert', create_time)
#event.listen(TimeStampMixin, 'before_update', modified_time)
所以我想创建一个我可以在任何类中应用的mixin:
class MyClass(TimeStampMixin, Base):
etc, etc, etc
此类继承在创建时创建时间戳并在更新时创建/修改时间戳的功能。
导入时出现此错误:
raise exc.UnmappedClassError(class_)
sqlalchemy.orm.exc.UnmappedClassError: Class 'db.database.TimeStampMixin' is not mapped
aaaand我在这一点上很难过。
答案 0 :(得分:34)
将您的侦听器附加到类方法中,它会将事件附加到子类。
class TimeStampMixin(object):
@staticmethod
def create_time(mapper, connection, target):
target.created = time()
@classmethod
def __declare_last__(cls):
# get called after mappings are completed
# http://docs.sqlalchemy.org/en/rel_0_7/orm/extensions/declarative.html#declare-last
event.listen(cls, 'before_insert', cls.create_time)
答案 1 :(得分:13)
以下是我要对before_insert
事件进行聆听的事项:向classmethod
添加TimeStampMixin
,注册当前类并处理设置创建时间。
E.g。
class TimeStampMixin(object):
# other class methods
@staticmethod
def create_time(mapper, connection, target):
target.created = time()
@classmethod
def register(cls):
sqlalchemy.event.listen(cls, 'before_insert', cls.create_time)
这样,您可以:
您可以简单地使用它:
class MyMappedClass(TimeStampMixin, Base):
pass
MyMappedClass.register()
简单,非常清晰,没有魔法,但仍然像你想要的那样封装。
答案 2 :(得分:2)
你也可以这样做:
from sqlalchemy.orm.interfaces import MapperExtension
class BaseExtension(MapperExtension):
"""Base entension class for all entities """
def before_insert(self, mapper, connection, instance):
""" set the created_at """
instance.created = datetime.datetime.now()
def before_update(self, mapper, connection, instance):
""" set the updated_at """
instance.modified = datetime.datetime.now()
class TimeStampMixin(object):
id = Column(Integer, primary_key=True, autoincrement=True)
created = Column(DateTime())
modified = Column(DateTime())
__table_args__ = {
'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8'
}
__mapper_args__ = { 'extension': BaseExtension() }
并定义您的类,如:
class User(TimeStampMixin, Base):
答案 3 :(得分:2)
现代SqlAlchemy的最佳方法是将@listens_for
装饰器与propagate=True
一起使用。
from datetime import datetime
from sqlalchemy import Column, Float
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.event import listens_for
class TimestampMixin():
@declared_attr
def created(cls):
return Column(DateTime(timezone=True))
@listens_for(TimeStampMixin, "init", propagate=True)
def timestamp_init(target, args, kwargs):
kwargs["created"] = datetime.utcnow()