Skip to main content

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 or database="*". (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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_pgware-1.0.0.tar.gz (23.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_pgware-1.0.0-py3-none-any.whl (21.0 kB view details)

Uploaded Python 3

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

Hashes for django_pgware-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e7aa705861881bf5c7f4a955220051049c86045a56c1c3933f44fc411c447ee6
MD5 695714efa368f126a3bcc3fe09ae9668
BLAKE2b-256 afdbd9f6b1e7e3bc07613b019009c2df6d3904e0dbfb7ac73dba4d3f00dc7c6e

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_pgware-1.0.0.tar.gz:

Publisher: publish.yml on Xof/django-pgware

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for django_pgware-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 658aba06d14e184b2a2e3895b1a1a179bc83cca75207da12ba2c6c2e956443db
MD5 a74c125c0cec1a7bddc878f6c2438a80
BLAKE2b-256 068af474e1b215cfc9c254a3b77377d780082dcbeb9320bd4c98492980c6aee8

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_pgware-1.0.0-py3-none-any.whl:

Publisher: publish.yml on Xof/django-pgware

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page