如果我有一个帖子列表,其中包含created
和updated
日期,并附带默认的onupdate
回调。
有时,为了inappropriate reports
或类似的操作,我需要标记这个帖子。我不希望修改created
和updated
日期。
如何在创建onupdate
操作时跳过定义的update
?
发布于 2021-10-20 11:43:28
SQLAlchemy将应用默认的什么时候
没有为该列的INSERT或UPDATE语句提供任何值。
然而,显而易见的解决办法--将列显式设置为其当前值--将无法工作,因为会话检查是否实际更改了值,如果没有更改,则不会传递值。以下是两种可能的解决方案,假设SQLAlchemy 1.4+和此模型:
class Post(db.Model):
flag = db.Column(db.Boolean, default=False)
last_updated = db.Column(db.DateTime, default=some_func, onupdate=some_func)
使用事件侦听器
添加一个检测标志列何时被修改的更新侦听器之前,并将时间戳列作为已修改的标记,即使其值不变。这将使SQLAlchemy将当前值添加到更新中,因此不会调用onupdate函数。
import sqlalchemy as sa
...
@sa.event.listens_for(Post, 'before_update')
def receive_before_update(mapper, connection, target):
insp = sa.inspect(target)
flag_changed, _, _ = insp.attrs.flag.history
if flag_changed:
orm.attributes.flag_modified(target, 'last_updated')
使用SQLAlchemy核心而不是ORM
SQLAlchemy核心不需要会话,因此可以将当前的时间戳值传递给更新,以避免触发onupdate函数。ORM将不知道以这种方式所做的任何更改,因此,如果在会话受影响对象的上下文中进行更改,则应该刷新或过期对象。这是一个“快速和肮脏”的解决方案,但如果标记发生在正常应用程序流之外,则可能足够好。
with db.engine.begin() as conn:
posts = Post.__table__
update = sa.update(posts).where(...).values(flag=True, last_updated=posts.c.last_updated)
conn.execute(update)
发布于 2022-11-09 12:41:25
您可以简单地分配带有SQLAlchemy核心级别列对象的列来发出SQL,比如'UPDATE post set created=post.created,updated=post.update‘。
class Post(Base):
id=Column(Integer,primary_key=True)
name=Column(String)
created=Column(DateTime,onupdate=func.now())
updated=Column(DateTime,onupdate=func.now())
post=session.query(Post).first()
post.name='updated post'
post.created= Post.__table__.c.created
post.updated= Post.__table__.c.updated
session.commit()
已发送的SQL:
UPDATE post SET name='updated post', created=post.created, updated=post.updated WHERE post.id=1;
https://stackoverflow.com/questions/69625550
复制相似问题