这是一个SQLAlchemy类:
class MyGroup(Base):
__tablename__ = 'my_group'
group_id = Column(Integer, Sequence('my_seq'), primary_key=True)
group_name = Column(String(200), nullable=False, index=True)
date_created = Column(DateTime, default=func.now())
date_updated = Column(DateTime, default=func.now(), onupdate=func.now())
无论何时添加group_name或(例如)更新group_name,date_updated
字段都会更新。太棒了。
但有时有些情况下我想将某个组标记为"更新"即使组记录本身没有改变(例如,如果更新了不同但相关的表中的数据)。
我可以手动完成:
group = session.query(MyGroup).filter(MyGroup.group_name=='Some Group').one()
group.date_updated = datetime.datetime.utcnow()
session.commit()
但我真的宁愿让模型以自己的方式完成它,而不是重新创建一个Python进程来手动更新日期。 (例如,为避免错误,例如模型使用now()
而手动功能错误地使用utcnow()
)
SQLAlchemy是否有办法触及"触摸"一条记录(有点像UNIX touch
),它不会改变任何记录的其他值,但会触发onupdate=
函数吗?
答案 0 :(得分:1)
我没有查看源代码,但是从docs看来这只是通过发出SQL UPDATE
命令来触发:
onupdate - 标量,Python可调用或ClauseElement,表示要在UPDATE语句中应用于列的默认值,如果此更新的SET子句中不存在此列,则会在更新时调用。这是将ColumnDefault用作for_update = True的位置参数的快捷方式。
如果您的关注点是确保您的“触摸”使用与onupdate
功能相同的功能,您可以在模型上定义一个方法来执行触摸,并使onupdate
参数指向此方法。
我认为这样的事情会起作用:
class MyGroup(Base):
__tablename__ = 'my_group'
group_id = Column(Integer, Sequence('my_seq'), primary_key=True)
group_name = Column(String(200), nullable=False, index=True)
date_created = Column(DateTime, default=func.now())
date_updated = Column(
DateTime,
default=self.get_todays_date,
onupdate=self.get_todays_date)
def get_todays_date(self):
return datetime.datetime.utcnow()
def update_date_updated(self):
self.date_updated = self.get_todays_date()
然后您可以像这样更新您的记录:
group.update_date_updated()
session.commit()
答案 1 :(得分:1)
documentation仅需添加以下内容即可:
Column.default和Column.onupdate关键字参数也接受Python函数。如果没有为该列提供其他任何值,则在插入或更新时将调用这些函数,并将返回的值用作该列的值。
关键部分:,如果没有为该列提供其他值,则在插入或更新时调用。 关键部分的关键部分:如果没有为该列提供其他值
因此,使用带有空值的简单更新语句,就可以做到:
from sqlalchemy import update
stmt = update(ModelName).where(ModelName.column.in_(column_values)).values()
db.engine.execute(update_product_mapping_info)
我正在为此documentation使用sqlalchemy.sql.expression.update
。
这是我的“模型”列定义:
from datetime import datetime
last_updated = Column(db.DateTime, onupdate=datetime.utcnow)
答案 2 :(得分:1)
为了显示一个完整的示例,我以@Chayemor的答案为基础:
import sqlalchemy.sql.functions as func
from sqlalchemy import Column, Integer, String, update
from . import database as db
Base = declarative_base()
class Object(Base):
__tablename__ = "objects"
id = Column(Integer, primary_key=True, nullable=False)
last_update = Column(
DateTime,
server_default=func.now(),
onupdate=func.current_timestamp()
)
def touch(self):
stmt = update(Game).where(Game.id == self.id)
db.engine.execute(stmt)
从此处开始,运行obj.touch()
将更新其在数据库中的last_update
字段,而无需更改任何其他数据。