SQLAlchemy中的属性自动更新
我有一个用sqlalchemy建立的模型,结构是这样的:
class Entry(Base):
__tablename__ = 'entries'
__table__ = Table('entries', Base.metadata,
Column('id', Integer, primary_key=True, unique=True),
Column('user_id', Integer, ForeignKey('users.id', onupdate="CASCADE", ondelete="RESTRICT")),
Column('title', String(128)),
Column('slug', String(128), index=True),
Column('url', String(256), index=True),
Column('entry', Text),
Column('cached_entry', Text),
Column('created', DateTime, server_default=text('current_timestamp')),
Column('modified', DateTime, server_onupdate=text('current_timestamp')),
Column('pubdate', DateTime),
)
我希望的是,当我更新entry
的时候,cached_entry
也能重新生成。cached_entry
是entry
的markdown解析版本。简单来说,我是在缓存markdown解析的结果,这样每次显示entry
的时候就不用再解析一次了。我尝试过使用@hybrid_method
,但是那似乎不行,因为它根本不存储在数据库里。我在Google AppEngine上搞定了这个,但我现在不知道怎么用SQLAlchemy做到同样的事情。
我真的不想在类里添加一个函数来替代模型中的名称,因为这样从应用的角度来看更难以管理,我不想不小心漏掉什么。
1 个回答
6
@hybrid_descriptor 确实是按照 这个链接 上描述的方式来实现的。你可以把数据库中对应的属性赋值给一个不同的名字。因为你在使用 __table__
,所以可以用类似这样的方式:
class Entry(Base):
__table__ = ...
_entry = __table__.c.entry
@hybrid_property
def entry(self):
return self._entry
@entry.setter
def entry(self, value):
self._entry = value
self.cached_entry = markdown(value)
另外一种方法是使用 before_insert 和 before_update 事件,在刷新数据时填充这个列。这种方法简单,但缺点是你得等到 flush() 才能看到效果。
我觉得最快的“设置”方式是使用 @validates:
from sqlalchemy.orm import validates
class Entry(Base):
__table__ = ...
@validates('entry')
def _set_entry(self, key, value):
self.cached_entry = markdown(value)
return value