Quick start
Requirements
- Python 3.12+
- Django 5.2 or 6.0
The API uses Django's built-in session auth; you do not need Django REST Framework.
Install
pip install django-report-builder
Then in settings.py:
INSTALLED_APPS = [
...
"report_builder",
]
And in urls.py:
from django.urls import include, path
urlpatterns = [
...
path("report_builder/", include("report_builder.urls")),
]
Run migrations:
python manage.py migrate
Now log into Django admin (/admin/) as a staff user, then visit
/report_builder/.
Settings
Limit which models are exposed
# Allow only specific models (app_label.model_name, lowercase)
REPORT_BUILDER_INCLUDE = ["hr.user", "billing.invoice"]
# Or block specific models
REPORT_BUILDER_EXCLUDE = ["finance.account"]
Per-model field control
Add a ReportBuilder inner class to a model — the syntax mirrors Django's
Meta:
class Order(models.Model):
...
class ReportBuilder:
fields = ("id", "customer", "total") # explicit allow-list
exclude = ("internal_notes",) # block specific fields
extra = ("display_total",) # methods/properties to expose
defaults = ("id", "customer") # default-on display fields
filters = ("customer", "status") # fields that surface as filters
fields and exclude are mutually exclusive; pick one. extra is how
Python properties get into reports — they're opt-in. defaults and filters
are advisory metadata — they're returned by the API for frontends that want
to use them.
Custom model managers
Use a different manager globally:
REPORT_BUILDER_MODEL_MANAGER = "on_site"
Or per-model, by adding the attribute on the model class:
class Order(models.Model):
on_site = OnSiteManager()
report_builder_model_manager = on_site
Export to Report admin action
Off by default. Turn on with:
REPORT_BUILDER_GLOBAL_EXPORT = True
Users can then select rows on a Django admin change-list and export them through a chosen report — the report's filters are bypassed in favor of the selected primary keys.
Asynchronous report generation
For reports that take long enough to risk an HTTP timeout, hand them off to a background worker:
REPORT_BUILDER_ASYNC_REPORT = True
The dispatch layer targets the standard django.tasks framework. Pick whichever backend fits your project:
- Django 6.0+ built-in
django.tasks— no extra package needed. Configure a backend via theTASKSsetting (the bundled in-memory / database backends are aimed at dev and testing). - django-vtasks — a faster
asyncio-worker backend for the same framework that can optionally be
embedded inside an ASGI app instead of running a separate worker.
pip install django-report-builder[vtasks], then configure the backend via theTASKSsetting (see vtasks' README). - django-tasks — a
drop-in backport of the built-in framework, for projects still on
Django 5.2.
pip install django-report-builder[tasks]. - Celery — if you already run Celery, the
dispatch layer detects it and hands off via
shared_task. Install withpip install django-report-builder[celery]. - Inline (synchronous) — used when none of the above is installed;
effectively the same as
REPORT_BUILDER_ASYNC_REPORT = False.
The dispatch layer auto-detects which is available in roughly the order
above. Switching is just pip install + a backend swap in the TASKS
setting; no report-builder code changes.
Email when an async report is ready
REPORT_BUILDER_EMAIL_NOTIFICATION = True
REPORT_BUILDER_EMAIL_SUBJECT = "Your report is ready"
Standard Django mail config applies (EMAIL_BACKEND or EMAIL_HOST, plus
DEFAULT_FROM_EMAIL). The email template is email/email_report.html and
can be overridden in your project's templates. {{ report }} and
{{ name }} are interpolated.
The bundled SPA still downloads the file directly — to actually use the email-only flow, build (or extend) your own frontend.
Scheduled reports
Recurring report runs are an opt-in app on top of Celery beat:
pip install django-celery-beat- Add
django_celery_beatandreport_builder_scheduledtoINSTALLED_APPS - Schedule a Celery beat task to run
report_builder_scheduled.tasks.report_builder_check_if_scheduled_reportevery ~10 minutes — it dispatches the actual report jobs
Disable the bundled frontend
If you're shipping your own SPA against the report builder API, hide the built-in one:
REPORT_BUILDER_FRONTEND = False