{"id":4514,"library":"django-pgtrigger","title":"django-pgtrigger","description":"django-pgtrigger is a Python library that enables the creation and management of PostgreSQL triggers directly from Django models. It simplifies the process of integrating powerful database-level logic, such as protecting operations, enforcing read-only fields, or soft-deleting models, into Django applications. The library is actively maintained, frequently releasing new versions to support the latest Django, Python, and PostgreSQL releases.","status":"active","version":"4.17.0","language":"en","source_language":"en","source_url":"https://github.com/AmbitionEng/django-pgtrigger","tags":["Django","Postgres","Database","Triggers"],"install":[{"cmd":"pip install django-pgtrigger","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core framework integration; compatible with Django 4.2 - 6.0.","package":"Django","optional":false},{"reason":"PostgreSQL adapter for Python; compatible with Psycopg 2 - 3.","package":"psycopg2/psycopg","optional":true},{"reason":"Database server where triggers are installed; compatible with Postgres 14 - 18.","package":"PostgreSQL","optional":true}],"imports":[{"note":"Main module containing Trigger classes and utilities.","symbol":"pgtrigger","correct":"import pgtrigger"},{"note":"A common trigger class for protecting model operations.","symbol":"Protect","correct":"from pgtrigger import Protect"},{"note":"An operation constant used with trigger classes.","symbol":"Delete","correct":"from pgtrigger import Delete"},{"note":"Used for building conditional logic, similar to Django's Q objects.","symbol":"Q","correct":"from pgtrigger import Q"},{"note":"Used for building conditional logic, similar to Django's F objects.","symbol":"F","correct":"from pgtrigger import F"}],"quickstart":{"code":"import pgtrigger\nfrom django.db import models\n\nclass ProtectedModel(models.Model):\n    name = models.CharField(max_length=100)\n\n    class Meta:\n        app_label = 'myapp'\n        triggers = [\n            pgtrigger.Protect(name=\"prevent_deletes\", operation=pgtrigger.Delete)\n        ]\n\n# To see this in action, after adding 'pgtrigger' to INSTALLED_APPS and 'myapp' to your Django project:\n# 1. python manage.py makemigrations\n# 2. python manage.py migrate\n# 3. From a Django shell:\n#    from myapp.models import ProtectedModel\n#    ProtectedModel.objects.create(name='Test')\n#    ProtectedModel.objects.first().delete() # This will raise a ProgrammingError from PostgreSQL","lang":"python","description":"To quickly get started, install `django-pgtrigger` and add `pgtrigger` to your `INSTALLED_APPS`. Define triggers directly in your Django model's `Meta.triggers` list using built-in trigger classes like `pgtrigger.Protect`. After defining, run `makemigrations` and `migrate` to install the triggers in your PostgreSQL database."},"warnings":[{"fix":"Upgrade Python to 3.10+ and PostgreSQL to 14+ or pin `django-pgtrigger<4.14.0` or `django-pgtrigger<4.16.0` respectively.","message":"Version 4.16.0 dropped support for Python 3.9, and version 4.14.0 dropped support for Postgres 13. Users on these older environments must upgrade their Python or PostgreSQL versions, or pin to an older django-pgtrigger version.","severity":"breaking","affected_versions":"4.14.0, 4.16.0"},{"fix":"Update calls from `pgtrigger.get` to `pgtrigger.registered`. For multi-database environments, ensure management commands include the `--database` argument. Run `python manage.py pgtrigger install` or `prune` to update old triggers.","message":"Version 4.0.0 introduced significant changes to multi-database and registry behavior. The `pgtrigger.get` function was renamed to `pgtrigger.registered`. Management commands (`install`, `uninstall`, `prune`, etc.) now operate on one database at a time and require the `--database` argument for multi-database setups.","severity":"breaking","affected_versions":"4.0.0+"},{"fix":"Migrate from using `@pgtrigger.register(...)` as a decorator to defining a `triggers` list in your model's `Meta` class, for example, `class Meta: triggers = [...]`.","message":"The `@pgtrigger.register` decorator on models is deprecated since version 3.0. While still functional, the recommended and fully supported way to define triggers is within the `Meta.triggers` list of your Django model.","severity":"deprecated","affected_versions":"3.0+"},{"fix":"Either enable `PGTRIGGER_MIGRATIONS` (default `True`), or ensure a post-deploy step runs `python manage.py pgtrigger install`, or set `PGTRIGGER_INSTALL_ON_MIGRATE = True` in settings.","message":"If `settings.PGTRIGGER_MIGRATIONS` is set to `False` to disable migration integration, triggers will not be automatically installed or updated via Django migrations. Manual installation via `python manage.py pgtrigger install` or setting `PGTRIGGER_INSTALL_ON_MIGRATE = True` is then required.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For third-party models, create a proxy model and define triggers in its `Meta.triggers`. Ensure `PGTRIGGER_SCHEMA_EDITOR` remains `True` (default) if you anticipate changing column types involved in trigger conditions.","message":"Registering triggers programmatically on models from third-party Django applications can create migrations in those apps, leading to potential issues with migration management. Additionally, altering column types used in trigger conditions can cause migration failures if `settings.PGTRIGGER_SCHEMA_EDITOR` is `False`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}