Si tengo una lista de publicaciones, que han created y updated fechas con una devolución de llamada de actualización adjunta onupdate .
A veces necesito marcar la publicación, por inappropriate reports o acciones similares. No quiero que se modifiquen las fechas de created y updated .
¿Cómo puedo omitir la actualización definida mientras onupdate una acción de update ?
SQLAlchemy aplicará un valor predeterminado cuando
no se proporcionó ningún valor a la declaración INSERT o UPDATE para esa columna
sin embargo, la solución obvia (establecer explícitamente la columna en su valor actual) no funcionará porque la sesión verifica si el valor realmente ha cambiado y no pasa un valor si no lo ha hecho. Aquí hay dos soluciones posibles, asumiendo SQLAlchemy 1.4+ y este modelo:
class Post(db.Model): flag = db.Column(db.Boolean, default=False) last_updated = db.Column(db.DateTime, default=some_func, onupdate=some_func)Agregue un agente de escucha antes de la actualización que detecte cuándo se modifica la columna de marca y marque la columna de marca de tiempo como modificada, aunque su valor no haya cambiado. Esto hará que SQLAlchemy agregue el valor actual a la actualización, por lo que no se llamará a la función 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 Core no necesita una sesión, por lo que el valor actual de la marca de tiempo se puede pasar a una actualización para evitar activar la función onupdate. El ORM no estará al tanto de los cambios realizados de esta manera, por lo que si se realiza dentro del contexto de una sesión, los objetos afectados deben actualizarse o caducar. Esta es una solución "rápida y sucia", pero podría ser lo suficientemente buena si el marcado ocurre fuera del flujo normal de la aplicación.
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)