django-postgres-extra

Brings PostgreSQL's advanced features (atomic upserts, table partitioning, materialized views, HStore) to the Django ORM with fully automatic migrations.

Library
PyPI
v2.0.9
762stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
62/100Good
Development Activity32
Maintenance48
Community80
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture82
Code Quality88
Innovation78
Learning Curve85

django-postgres-extra extends the Django ORM with PostgreSQL-specific capabilities that Django’s database-agnostic core deliberately leaves out. Instead of bolting on a handful of raw-SQL helpers, it replaces the database backend and schema editor so that atomic upserts, declarative table partitioning, materialized/regular views, schema management, explicit locking, and HStore fields all behave like native Django features — including full support in makemigrations and migrate, with no hand-written migration operations required.

The project has been maintained by Sector Labs since 2017, tracks current Django and Python releases closely (Django 2.0-6.0, Python 3.7-3.13), and supports both psycopg2 and psycopg3. It ships as a small, focused dependency surface (just Django and python-dateutil) precisely because its value comes from deep integration with Django’s own internals rather than wrapping a separate client library.

What You Get

  • A custom database backend and schema editor (psqlextra.backend) that emits PostgreSQL-native DDL for partitioning, views, and constraints
  • PostgresModel / PostgresManager / PostgresQuerySet drop-in replacements that add .on_conflict() atomic upsert support to the standard Django ORM
  • Declarative table partitioning (range and time-based) fully integrated into makemigrations, including a management command to auto-create future partitions
  • Support for regular and materialized views defined as ordinary Django models, kept in sync through migrations
  • A patched migration autodetector so partitioning, view, and HStore-constraint changes are captured automatically instead of requiring manual migration authoring
  • HStore field support with unique and required-key constraints enforced at the database level

Common Use Cases

  • Replacing manual INSERT ... ON CONFLICT raw SQL with a typed, queryset-level atomic upsert API
  • Partitioning large, time-series or high-write tables (events, logs, metrics) by range or time without leaving Django’s migration system
  • Backing reporting or read-heavy views with PostgreSQL materialized views that are still modeled and migrated like regular Django models
  • Enforcing uniqueness or required-ness on individual HStore keys at the database layer instead of in application code
  • Taking explicit table-level locks or dropping/creating PostgreSQL schemas from within Django code and migrations

Under The Hood

Architecture The package layers around a custom Django database backend (psqlextra/backend/base.py, base_impl.py) that subclasses Django’s PostgreSQL backend and wires in a custom schema editor (backend/schema.py) hooking DDL emission for partitioning, views, locking, and truncation, plus side-effect modules (backend/side_effects/hstore_required.py, hstore_unique.py) that inject HStore constraint validation into the migration-execution pipeline. Migration awareness comes from patches to Django’s own machinery (backend/migrations/patched_autodetector.py, patched_migrations.py, patched_project_state.py), extending the autodetector so partitioning, view, and HStore-specific state changes are captured automatically. On the query side, PostgresManager (manager/manager.py) requires the psqlextra backend to be configured and returns a PostgresQuerySet (query.py) that overrides insert/annotate/upsert behavior, building PostgresQuery/PostgresInsertQuery objects (sql.py) that compile into ON CONFLICT-aware SQL. Partitioning is its own subsystem (partitioning/) with a manager, pluggable strategies, and a reconciliation “plan” that diffs desired schema against introspected state (introspect/). The schema editor is the single load-bearing abstraction — every side effect and migration operation hooks through it.

Tech Stack Pure Python targeting Django 2.0-6.0 across Python 3.7-3.13, with a deliberately minimal dependency surface (Django and python-dateutil only) since the value comes from extending Django’s own backend rather than wrapping a separate driver — both psycopg2 and psycopg3 are supported through Django’s standard backend configuration. Development tooling is uv-managed, with black for formatting, flake8 for linting, mypy plus django-stubs for type-checking, isort for import order, and poethepoet as the task runner tying these together; documentation is built with Sphinx and published to Read the Docs. CI runs the test suite against a live PostgreSQL service across the full Python/Django/psycopg matrix via tox, with a separate tag-triggered workflow building and publishing releases to PyPI.

Code Quality Tests are extensive — dozens of test modules covering conflict handling, partitioning, views, HStore constraints, migrations, and locking, run with pytest and pytest-django, snapshot-tested via syrupy, and benchmarked with pytest-benchmark, with coverage reported to Coveralls in CI. Error handling is explicit and typed rather than swallowed: ImproperlyConfigured and SuspiciousOperation are raised deliberately at integration boundaries, such as PostgresManager refusing to initialize if the psqlextra backend isn’t configured. Naming mirrors Django’s own conventions (PostgresQuerySet, PostgresManager, PostgresSchemaEditor), the codebase ships a py.typed marker and is checked with mypy plus django-stubs, and formatting/linting/import order are all enforced through a single poe verify task.

API Design The public API deliberately mirrors Django’s own conventions so adopting it requires no new mental model: subclass PostgresModel, swap in PostgresManager, and atomic upserts, partitioning, and views become ordinary queryset methods and model base classes rather than a separate DSL. Migrations stay fully automatic — the patched autodetector understands partitioning config, view models, and HStore constraints, so makemigrations produces correct operations without hand-authored migration code, a level of integration most single-feature Postgres-for-Django add-ons don’t attempt. Documentation is thorough, with a dedicated Sphinx site covering each feature area plus a precise version-compatibility matrix in the README, lowering the risk of adopting a database-specific extension.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search