mysqlalchemy table operation audit
mysqlalchemy audit extension
https://sqlalchemy-declarative-extensions.readthedocs.io/en/stable/audit_tables.html
from sqlalchemy import Column, types from sqlalchemy.orm import declarative_base from sqlalchemy_declarative_extensions import declarative_database from sqlalchemy_declarative_extensions.audit import audit Base = declarative_database(declarative_base()) @audit() class Foo(Base): __tablename__ = "foo" id = Column(types.Integer(), primary_key=True) name = Column(types.Unicode()) json = Column(JSONB()) audit_table = Foo.__audit_table__
change
foo1 = Foo(id=1, name=None, json=None) foo2 = Foo(id=2, name='wat?', json={}) pg.add(foo1) pg.add(foo2) pg.commit() foo1.name = 'wow!' pg.delete(foo2) pg.commit()
audit table
sqlalchemy-continuum
https://github.com/kvesteri/sqlalchemy-continuum
https://sqlalchemy-continuum.readthedocs.io/en/latest/intro.html
Features
Creates versions for inserts, deletes and updates
Does not store updates which don't change anything
Supports alembic migrations
Can revert objects data as well as all object relations at given transaction even if the object was deleted
Transactions can be queried afterwards using SQLAlchemy query syntax
Query for changed records at given transaction
Temporal relationship reflection. Version object's relationship show the parent objects relationships as they where in that point in time.
Supports native versioning for PostgreSQL database (trigger based versioning)
from sqlalchemy_continuum import make_versioned from sqlalchemy import Column, Integer, Unicode, UnicodeText, create_engine from sqlalchemy.orm import create_session, configure_mappers, declarative_base make_versioned(user_cls=None) Base = declarative_base() class Article(Base): __versioned__ = {} __tablename__ = 'article' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(Unicode(255)) content = Column(UnicodeText) configure_mappers() engine = create_engine('sqlite://') Base.metadata.create_all(engine) session = create_session(bind=engine, autocommit=False) article = Article(name=u'Some article', content=u'Some content') session.add(article) session.commit() article.versions[0].name article.name = u'Updated name' session.commit() article.versions[1].name article.versions[0].revert() article.name