Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

sqlalchemy-pgtrigger

sqlalchemy rewrite of django-pgtrigger

Installation

uv add sqlalchemy-pgtrigger

Alembic integration is optional, allowing trigger installation through migrations:

uv add sqlalchemy-pgtrigger[alembic]

Declaring a trigger

Triggers inherit from SchemaItem, so they can go in __table_args__ next to indices and constraints. The vocabulary follows the CREATE TRIGGER grammar, so a declaration and the statement it produces line up clause for clause.

import pgtrigger

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column


class Document(DeclarativeBase):
    __tablename__ = "documents"

    id: Mapped[int] = mapped_column(primary_key=True)
    body: Mapped[str]
    published: Mapped[bool] = mapped_column(default=False)
    deleted: Mapped[bool] = mapped_column(default=False)

    __table_args__ = (
        # once a document is published its body is fixed
        pgtrigger.ReadOnly(
            condition=(lambda old, new: old.published.is_(True)),
            fields=("body",),
            name="published_body_is_final",
        ),
        # a DELETE marks the row rather than removing it
        pgtrigger.SoftDelete(field="deleted", name="mark_deleted"),
    )

Conditions are ordinary SQLAlchemy expressions over the old and new rows, so the expression language handles the quoting, the types, and the literals. The first trigger above compiles to:

WHEN ((OLD.body IS DISTINCT FROM NEW.body) AND (OLD.published IS true))

Installing triggers

create_all installs whatever is declared on the tables it creates, which is usually what you want in tests:

Document.metadata.create_all(engine)

Everywhere else, triggers must be installed explicitly:

from pgtrigger.installation import install, status, uninstall

install(engine)  # everything registered
install(engine, "documents:mark_deleted")  # one trigger
install(session, "documents:*")  # one table
status(engine)  # declared vs installed

Every function takes the connectable first; an Engine gets a transaction of its own, a Connection or Session joins one already open.

To keep triggers in migrations instead, import the Alembic integration from your env.py, and let pgtrigger.migrations.autogenerate find them:

# alembic/env.py
import pgtrigger.migrations

Each installed trigger carries a fingerprint of its own definition, so autogenerate diffs declarations against the database rather than against migration state. A revision records the finished SQL, so editing a declaration later never rewrites migration history.

Acknowledgements

A special thanks to the team at Ambition and all the contributors behind django-pgtrigger.

Their excellent work on managing PostgreSQL triggers in Django served as the architectural foundation for this library.

License

This project is licensed under the BSD-3-Clause license.

Metadata

Release files for sqlalchemy-pgtrigger 0.0.0a1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sqlalchemy-pgtrigger 0.0.0a1
File Size Uploaded
sqlalchemy_pgtrigger-0.0.0a1.tar.gz 49.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sqlalchemy-pgtrigger 0.0.0a1
File Interpreter ABI Platform
sqlalchemy_pgtrigger-0.0.0a1-py3-none-any.whl Python 3 none any Details

Total release size: 123.6 kB

Release files / sqlalchemy_pgtrigger-0.0.0a1.tar.gz

Download URL sqlalchemy_pgtrigger-0.0.0a1.tar.gz
Size 49.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c1c36a6f5a2d5e1690c496b4c7bfb39cc3959191787b364055ad5016a889ac8b
BLAKE2b-256 checksum
How to use checksums
06d387ded802ba250921be9045c7cfbdbc76879c557bdddc6afff948b7be3d80
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / sqlalchemy_pgtrigger-0.0.0a1-py3-none-any.whl

Download URL sqlalchemy_pgtrigger-0.0.0a1-py3-none-any.whl
Size 74.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0b247d89d3467828d33af6f4744c5cda20bd58573b728d18f78592e851e0bdc5
BLAKE2b-256 checksum
How to use checksums
cdf462c5a0f0391fcae84fe64d11f0489f41eedc548493f6007959a5d8d044e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.0.0a1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page