Skip to main content

Django Flexible Reports

PyPI Version Python Version Tests Docs License

A framework for database-defined reports in Django.

Instead of hardcoding a report in a template or a view, you describe it in the database — which rows it shows, which columns it has, how the cells are formatted, how it is sorted — and edit all of that through the Django admin. Your application code only picks a report, hands it a queryset and renders it with one template tag:

{% load flexible_reports_tags %}
{% flexible report %}

Rendering is done by django-tables2, so you get sortable headers, footers/totals and export for free.

Supported Versions

Python 3.10 Python 3.11 Python 3.12 Python 3.13 Python 3.14
Django 5.2 LTS
Django 6.0
Django 6.1

Django 6.0 and 6.1 require Python 3.12+. Django 4.2, 5.0 and 5.1 are no longer supported or tested — the floor is Django 5.2 LTS.

Documentation

The full documentation is at https://mpasternak.github.io/django-flexible-reports/.

Features

  • Reports live in the database, not in your code. Datasource, Table, Column, ColumnOrder, Report and ReportElement are ordinary Django models with a full admin, so non-programmers can change what a report shows without a deployment.
  • Two query languages for selecting rows. A Datasource narrows a base queryset using either django-dsl (the default) or DjangoQL, chosen per datasource.
  • Parametrised queries. Every query is rendered as a Django template first, so it can take values from the report context (pages > {{ min_pages }}). A sample_context field supplies example values so a parametrised query can still be validated when it is saved.
  • Query shortcuts. A model can declare django_dsl_shortcuts = {"author": "author__name"} and datasources may then use the short name.
  • Queries are validated on save. The admin refuses a query that does not compile or that the database rejects, instead of producing a silently empty report.
  • Columns are templates. A column either reads an attribute (attr_name, dot notation crosses relations: author.name) or renders a Django template snippet with record, value and default in its context — or both.
  • Footers and totals. display_totals sums a column and renders footer_template with value, count and error.
  • Coordinated sorting. Tables can sort independently, in a named group, or all together — clicking one header re-sorts every table on the page that has a column with the same label.
  • Default ordering per table via ColumnOrder (any number of columns, ascending or descending).
  • "Everything else" tables. A report element can be fed with except catchall data: every record from the base queryset that none of the report's datasources picked up.
  • Export. A report renders to HTML, to a .docx (through pypandoc) or to a tablib Dataset/Databook (CSV, XLSX, …). Columns can be excluded from export or have their HTML stripped.
  • Cloning. Table.clone() and Report.clone() — plus a Clone button on the admin change form — copy a definition (a table with its columns and sort order, a report with its elements) under a (copy) name.
  • Optional grappelli support, detected at import time: inlines become drag-and-drop sortable when grappelli is installed, with no configuration.
  • Translatable: all model verbose names, help texts and admin labels use gettext.

Quickstart

Install Django Flexible Reports, with uv:

uv add django-flexible-reports

or with pip:

pip install django-flexible-reports

Add it (and django_tables2, which renders the tables) to your INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "django.contrib.admin",          # to edit reports
    "django.contrib.contenttypes",   # required: models point at ContentType
    ...
    "django_tables2",
    "flexible_reports",
]

Make sure the request context processor is enabled — the {% flexible %} tag passes the surrounding template context to django-tables2, which needs request in it:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        ...
        "OPTIONS": {
            "context_processors": [
                ...
                "django.template.context_processors.request",
            ],
        },
    },
]

Then run the migrations:

python manage.py migrate

No URL patterns to include. flexible_reports.urls exists but is empty — the app ships no views of its own. You render reports from your own views. (Any instructions telling you to include(flexible_reports.urls) are obsolete.)

Now define a report in the admin (Flexible reports → Datasources / Tables / Reports) and render it from your own view:

from django.shortcuts import render

from flexible_reports.models import Report

from .models import Book


def library_report(request):
    report = Report.objects.get(slug="library-report")
    # Required: every datasource narrows *this* queryset.
    report.set_base_queryset(Book.objects.select_related("author"))
    # Optional: values for parametrised queries, e.g. "pages > {{ min_pages }}".
    report.set_context({"min_pages": 300})
    return render(request, "library/report.html", {"report": report})
{% load flexible_reports_tags %}
{% flexible report %}

That is the whole integration. Which tables the report has, which columns they carry, how they are sorted and how the cells look is all read from the database.

Demo project

A complete, self-contained demo lives in demo/ — two models, two datasources (one per query language, one of them parametrised), a table with six columns (dot notation, custom cell templates, totals) and a three-element report including an except catchall table. It runs on SQLite, so no services are needed:

make demo             # stock Django admin,       http://127.0.0.1:8000/
make demo-grappelli   # django-grappelli admin,   http://127.0.0.1:8001/
make demo-reset       # throw the demo database away

Log into the admin as admin / admin. See demo/README.md for a walkthrough of what the seeded report demonstrates.

Optional system dependencies

  • Exporting a report to .docx shells out to pandoc through pypandoc, so pandoc has to be installed on the machine (apt install pandoc, brew install pandoc).
  • Writing .xlsx needs openpyxl (pip install "tablib[xlsx]"), which tablib does not pull in by default. CSV/JSON/YAML/TSV work out of the box.

HTML rendering needs nothing extra.

Running Tests

uv sync --all-extras
uv run pytest

The test suite runs against PostgreSQL; see tests/settings.py (the POSTGRES_HOST / POSTGRES_PORT environment variables are honoured), or start one with the bundled docker-compose.yml.

Contributing

See CONTRIBUTING.md for the development setup, how to run the tests and the grappelli integration run, linting, and what CI checks. The changelog is HISTORY.md.

The manual under docs/ is Markdown, built with MkDocs and the Material theme:

make docs         # live preview on http://127.0.0.1:8000/
make docs-build   # build with --strict, exactly as CI does

License

MIT

Release files for django-flexible-reports 0.5.0

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

Source distribution (sdist)

Source distribution for django-flexible-reports 0.5.0
File Size Uploaded
django_flexible_reports-0.5.0.tar.gz 35.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-flexible-reports 0.5.0
File Interpreter ABI Platform
django_flexible_reports-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 88.8 kB

Release files / django_flexible_reports-0.5.0.tar.gz

Download URL django_flexible_reports-0.5.0.tar.gz
Size 35.6 kB
Tags Source
SHA-256 checksum
How to use checksums
181e9042d95de7282d1d94b09200a8ea2ae37a0eb0032d10693a2ab8ec07c4ec
BLAKE2b-256 checksum
How to use checksums
a150704b363c4f2040f0ffd557f8e6e1e969a291aef073781a45bf20a73c6e5a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release files / django_flexible_reports-0.5.0-py3-none-any.whl

Download URL django_flexible_reports-0.5.0-py3-none-any.whl
Size 53.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e9cb14dcd1e61e3256f67b0dddbcd3399ba7c5c1d4e009ad1975713035e942b3
BLAKE2b-256 checksum
How to use checksums
62cf9706122019a583c6238970657442edb10cc03ac933199a783421b2bbca0d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.12

2 release files

0.2.11

2 release files

0.2.10

1 release file

0.2.9

1 release file

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.25

2 release files

0.1.23

2 release files

0.1.21

2 release files

0.1.20

2 release files

0.1.19

2 release files

0.1.16

2 release files

0.1.15

2 release files

0.1.14

2 release files

0.1.13

2 release files

0.1.11

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

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