sqlalchemy 监听所有实体插入以及更新事件

这边使用的是flask+dependency-injecter+sqlalchemy,有一个公共类,想插入或者更新的时候对公共类某些字段进行统一操作

这个是公共类:包括一些基础字段,所有的实体都会继承这个类

python 复制代码
"""Models module."""

from datetime import datetime
from sqlalchemy import Column, String, Integer,DateTime#, Boolean

from sqlalchemy.ext.declarative import declarative_base


Base = declarative_base()

class CommonEntity(Base):
    __abstract__ = True

    created_dt = Column(DateTime)
    created_by = Column(String)
    updated_dt = Column(DateTime)
    updated_by = Column(String)
    version = Column(Integer)

然后是db的配置

python 复制代码
"""Database module."""

from contextlib import contextmanager, AbstractContextManager
from typing import Callable

from sqlalchemy import create_engine, orm,event
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from datetime import datetime

from main.services.common_service.db_access.domain.common_field_entity import CommonEntity
Base = declarative_base()

class DatabaseConfig:

    def __init__(self, db_url: str) -> None:
        self._engine = create_engine(db_url, echo=True)
        self._session_factory = orm.scoped_session(
            orm.sessionmaker(
                autocommit=False,
                autoflush=False,
                expire_on_commit=False,
                bind=self._engine,
            ),
        )

    def create_database(self) -> None:
        Base.metadata.create_all(self._engine)


    @contextmanager
    def session(self) -> Callable[..., AbstractContextManager[Session]]:
        session: Session = self._session_factory()
        try:
            yield session
        except Exception:
            session.rollback()
            raise
        else:
            if session._transaction.is_active:
                session.commit()
            session.close()

    @event.listens_for(CommonEntity, 'before_insert', propagate=True)
    def before_insert_listener(self, mapper, target):
        # 在创建时自动更新 created_dt,version
        target.created_dt = datetime.now()
        target.created_by = 'Damien'
        target.version = 1
        
    @event.listens_for(CommonEntity, 'before_update', propagate=True)
    def before_update_listener(self, mapper, target):
        # 在更新时自动更新 updated_dt,version
        target.updated_dt = datetime.now()
        target.updated_by = 'Damien'
        target.version += 1

重要的就是@event.listens_for,这里。监听公共类,所有继承了它的实体的插入更新都会被监听到,然后就是对里面的字段进行统一的操作就行了,不用再每次插入或者更新进行手动修改了

相关推荐
l1t13 分钟前
DeepSeek总结的面向 PostgreSQL 分析和 HTAP 工作负载的两种高性能表访问方法
数据库·postgresql
九皇叔叔14 分钟前
MySQL 8.x 隔离级别调整
数据库·mysql·事务·隔离级别
许愿OvO16 分钟前
Redis 7.4.8高可用集群实战:主从复制+哨兵+Cluster全解析
数据库·redis·bootstrap
2401_8314194417 分钟前
如何用 http 模块创建一个基础的 Web 服务器处理请求
jvm·数据库·python
pele17 分钟前
Redis如何防止AOF文件无限增大_触发BGREWRITEAOF命令进行日志重写
jvm·数据库·python
qq_4142565717 分钟前
golang如何设计HTTP中间件链_golang HTTP中间件链设计方法
jvm·数据库·python
m0_7467523018 分钟前
如何用方法简写语法在对象字面量中快速定义成员函数
jvm·数据库·python
qq_1898070320 分钟前
JavaScript 中高效定位二维数组间不匹配元素的行列索引
jvm·数据库·python
qq_3493174823 分钟前
Python GUI界面如何实现主题美化_引入ttk模块实现原生外观风格
jvm·数据库·python
草履虫君25 分钟前
我们用纯命令行方式,给openclaw配置minimax2.7
数据库·经验分享·功能测试·ai