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

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

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

"""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的配置

"""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,这里。监听公共类,所有继承了它的实体的插入更新都会被监听到,然后就是对里面的字段进行统一的操作就行了,不用再每次插入或者更新进行手动修改了

A: SQLAlchemy 可以使用 `Insert` 和 `Update` 语句来实现批量插入更新。具体地,可以使用以下方式来实现: 1. 对于批量插入,可以使用 `insert()` 方法和 `values()` 方法,如下所示: ``` from sqlalchemy import create_engine, insert # 创建数据库连接 engine = create_engine('mysql+pymysql://user:password@localhost/test_db') # 构造数据 data = [ {'id': 1, 'name': 'Alice', 'age': 20}, {'id': 2, 'name': 'Bob', 'age': 22}, {'id': 3, 'name': 'Charlie', 'age': 25} ] # 定义表对象和元数据 metadata = MetaData() user_table = Table('user', metadata, Column('id', Integer, primary_key=True), Column('name', String(50)), Column('age', Integer)) # 插入数据 stmt = insert(user_table).values(data) conn = engine.connect() conn.execute(stmt) conn.close() ``` 2. 对于更新,可以使用 `update()` 方法和 `where()` 方法,如下所示: ``` from sqlalchemy import create_engine, update # 创建数据库连接 engine = create_engine('mysql+pymysql://user:password@localhost/test_db') # 定义表对象和元数据 metadata = MetaData() user_table = Table('user', metadata, Column('id', Integer, primary_key=True), Column('name', String(50)), Column('age', Integer)) # 更新 stmt = update(user_table).where(user_table.c.id == 1)\ .values(name='Alice', age=21) conn = engine.connect() conn.execute(stmt) conn.close() ``` 3. 对于**存在指定属性,则更新其他属性**的情况,可以使用 `on_duplicate_key_update()` 方法(需要 MySQL 5.5.3 或以上版本),如下所示: ``` from sqlalchemy.dialects.mysql import insert # 创建数据库连接 engine = create_engine('mysql+pymysql://user:password@localhost/test_db') # 构造数据 data = [ {'id': 1, 'name': 'Alice', 'age': 20}, {'id': 2, 'name': 'Bob', 'age': 22}, {'id': 3, 'name': 'Charlie', 'age': 25} ] # 定义表对象和元数据 metadata = MetaData() user_table = Table('user', metadata, Column('id', Integer, primary_key=True), Column('name', String(50)), Column('age', Integer)) # 插入更新数据 stmt = insert(user_table).values(data)\ .on_duplicate_key_update(name=inserted.name, age=inserted.age) conn = engine.connect() conn.execute(stmt) conn.close() ``` 其中,`inserted` 是指 `VALUES` 子句中插入的值,可以将它看做一个占位符,使用 `on_duplicate_key_update()` 方法将更新指定属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值