PostgreSQL utilities for Django: advisory locks, GUC management, and logging suppression
Project description
django-pgware
PostgreSQL utilities for Django: advisory locks, GUC management, and logging suppression.
What it is
A small, dependency-light toolkit of three independent PostgreSQL utilities for Django. Each is a context manager (and, where it makes sense, a decorator) that borrows Django's database connection, performs a session-scoped action, and reliably undoes it on exit: advisory locks (sync + async), GUC setting (pg_set / atomic_set), and logging suppression (hush, for keeping sensitive query parameters out of the logs).
See ARCHITECTURE.md for the internals and invariants, and THEORY.md for the design rationale.
Status
Beta (1.0.x). The public API is stable; see CHANGELOG.md for recent changes.
Installation
pip install django-pgware
You'll also need a PostgreSQL database adapter — either psycopg2 or psycopg (v3):
pip install django-pgware[psycopg2]
# or
pip install django-pgware[psycopg3]
Advisory Locks
Context managers for PostgreSQL advisory locks — synchronous and asynchronous.
from django_pg_utils import advisory_lock
# Exclusive lock (blocks until acquired):
with advisory_lock("my-task") as acquired:
assert acquired is True
do_exclusive_work()
# Shared lock:
with advisory_lock("my-task", shared=True):
do_shared_work()
# Non-blocking:
with advisory_lock("my-task", wait=False) as acquired:
if acquired:
do_work()
Async
from django_pg_utils import async_advisory_lock
async with async_advisory_lock("my-task") as acquired:
await do_work()
Lock ID Types
| Type | Example | Notes |
|---|---|---|
str |
"my-lock" |
Hashed to 64-bit via SHA-256 |
int |
12345 |
Used directly as bigint |
tuple[int, int] |
(5, 9) |
Two-argument advisory lock |
Parameters
| Parameter | Default | Description |
|---|---|---|
lock_id |
required | String, int, or (int, int) tuple |
shared |
False |
Shared lock (vs exclusive) |
wait |
True |
Block until acquired |
comment |
None |
Toggle the auto-generated file:line SQL comment. If None, resolves to settings.ADVISORY_LOCK_COMMENT if set, else settings.DEBUG |
using |
None |
Django database alias |
GUC Management
Temporarily SET PostgreSQL GUCs within a scope, with automatic cleanup.
pg_set — session-level SET / RESET
from django_pg_utils import pg_set
with pg_set("work_mem", "256MB"):
MyModel.objects.complex_query()
# Multiple GUCs:
with pg_set([("work_mem", "256MB"), ("statement_timeout", "30s")]):
...
# As a decorator:
@pg_set("work_mem", "256MB")
def my_view(request):
...
atomic_set — transaction-level SET LOCAL
from django_pg_utils import atomic_set
with atomic_set("work_mem", "256MB"):
MyModel.objects.complex_query()
Wraps the scope in atomic() and uses SET LOCAL — settings revert automatically when the transaction ends.
When to use which
pg_set |
atomic_set |
|
|---|---|---|
| Mechanism | SET / RESET |
SET LOCAL inside atomic() |
| Scope | Session (connection) | Transaction |
| Cleanup | Explicit RESET on exit |
Automatic on COMMIT / ROLLBACK |
Logging Suppression (hush)
Suppress PostgreSQL server logging and Django query logging within a scope — useful for protecting sensitive data (PCI cardholder data, credentials, tokens).
from django_pg_utils import hush
# Context manager:
with hush() as result:
cursor.execute("SELECT decrypt_card(%s)", [card_token])
# Decorator:
@hush
def process_payment(card_token):
...
# Parameterized:
@hush(strict=True, database="payments")
def process_payment(card_token):
...
Parameters
| Parameter | Default | Description |
|---|---|---|
database |
default connection | Django database alias. Pass "*" to suppress on every configured connection |
settings |
all 5 defaults | List of PG setting names to suppress |
strict |
False |
Raise HushError if suppression incomplete |
hush()targets only the default connection unless you pass an explicit alias ordatabase="*". (Earlier behavior suppressed on every configured connection by default, which would dial replicas/analytics DBs as a side effect.)
Django Settings
| Setting | Description |
|---|---|
HUSH_DATABASE |
Default database alias |
HUSH_SETTINGS |
Default settings list |
HUSH_STRICT |
Default strict mode |
HUSH_PG_SETTINGS_REGISTRY |
Dict replacing default PG settings |
Running the tests
The project uses uv. Tests require a live PostgreSQL — there is no sqlite fallback.
uv sync # install the dev environment
docker compose up -d # throwaway PostgreSQL on localhost:5432
uv run pytest # run the suite
PG_VERSION selects the PostgreSQL image (default 17); POSTGRES_HOST/PORT/USER/PASSWORD/DB override the connection. Lint and types: uv run ruff check && uv run ruff format --check && uv run mypy.
Requirements
- Python 3.10+
- Django 4.2+
- PostgreSQL 14+ with psycopg2 or psycopg3
License
PostgreSQL License. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_pgware-1.0.0.tar.gz.
File metadata
- Download URL: django_pgware-1.0.0.tar.gz
- Upload date:
- Size: 23.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7aa705861881bf5c7f4a955220051049c86045a56c1c3933f44fc411c447ee6
|
|
| MD5 |
695714efa368f126a3bcc3fe09ae9668
|
|
| BLAKE2b-256 |
afdbd9f6b1e7e3bc07613b019009c2df6d3904e0dbfb7ac73dba4d3f00dc7c6e
|
Provenance
The following attestation bundles were made for django_pgware-1.0.0.tar.gz:
Publisher:
publish.yml on Xof/django-pgware
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_pgware-1.0.0.tar.gz -
Subject digest:
e7aa705861881bf5c7f4a955220051049c86045a56c1c3933f44fc411c447ee6 - Sigstore transparency entry: 1893050417
- Sigstore integration time:
-
Permalink:
Xof/django-pgware@d7890145ee7adaf28df97569b199d9dccacb872d -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Xof
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d7890145ee7adaf28df97569b199d9dccacb872d -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_pgware-1.0.0-py3-none-any.whl.
File metadata
- Download URL: django_pgware-1.0.0-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
658aba06d14e184b2a2e3895b1a1a179bc83cca75207da12ba2c6c2e956443db
|
|
| MD5 |
a74c125c0cec1a7bddc878f6c2438a80
|
|
| BLAKE2b-256 |
068af474e1b215cfc9c254a3b77377d780082dcbeb9320bd4c98492980c6aee8
|
Provenance
The following attestation bundles were made for django_pgware-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on Xof/django-pgware
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_pgware-1.0.0-py3-none-any.whl -
Subject digest:
658aba06d14e184b2a2e3895b1a1a179bc83cca75207da12ba2c6c2e956443db - Sigstore transparency entry: 1893050549
- Sigstore integration time:
-
Permalink:
Xof/django-pgware@d7890145ee7adaf28df97569b199d9dccacb872d -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Xof
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d7890145ee7adaf28df97569b199d9dccacb872d -
Trigger Event:
release
-
Statement type: