Skip to content

Using report builder

A staff user with is_staff = True who can log into Django admin can use the report builder. Visit /report_builder/ after logging in.

The dashboard

The home view lists every report you have permission to see. A search box above the table filters by name. Click a report's name to open it, or Add Report to create a new one. Each row also has copy and delete actions.

Creating a report

Add Report asks for two things:

  • Name — what users see on the dashboard
  • Root model — the Django model the report is anchored on. Filters and display fields all hang off this; relations are reachable, but the starting point matters

Save and you'll land on the editor.

The editor

The editor is four tabs across the top — Display, Filter, Report, Options. The right-hand sidebar lists every field reachable from the root model.

Display

This is the column list. From the sidebar:

  • Click a related-model node in the tree to expand it; click its name to load that model's fields into the bottom of the sidebar
  • Click the + next to a field to add it as a column
  • Drag the row's grip handle to reorder columns within the table
  • Edit Name to rename the column header
  • Sort + Desc? control the ORM ordering. Sort is a positive integer — lower numbers sort first (so 1, 2, 3 orders by the first column, then the second, etc.). Leave it blank (or 0) to skip sorting on that column.
  • Aggregate turns the column into Sum / Count / Avg / Max / Min
  • Format applies a stored format string (configured under /admin/report_builder/format/)
  • Total and Group add a totals row and GROUP BY semantics

Filter

Same sidebar workflow — click + next to a field to add it as a filter. Each filter row has:

  • A Filter type dropdown (exact, gt, icontains, range, relative_range, isnull, regex, etc.)
  • A Value input that adapts to the field type — text fields get a textbox, dates get a date input, booleans get a checkbox, relative_range gets a number + unit picker
  • An Exclude checkbox to invert the match (.exclude() instead of .filter())

Report

Generate the result set in-browser. From there you can export to xlsx or csv — synchronously by default, or as a background task if REPORT_BUILDER_ASYNC_REPORT is on (the export button shows progress and the file becomes available on the same screen when ready).

Options

  • Description — visible on the report list
  • Distinct — adds .distinct() to the underlying queryset; useful when joining many-to-many relations produces duplicate rows
  • Delete and Copy for the report

Tips

  • If a model isn't appearing in the sidebar, check REPORT_BUILDER_INCLUDE / REPORT_BUILDER_EXCLUDE, plus the fields / exclude lists in the model's ReportBuilder inner class.
  • Properties (Python @property methods on a model) won't show up unless you list them in ReportBuilder.extra — and they slow report generation noticeably, since each row is computed in Python rather than the database.
  • relative_range filters express a window relative to "now". The UI shows a number plus a unit ("7 days ago"); under the hood the unit string is stored in filter_value and a negative-seconds offset in filter_delta (so "7 days ago" is -604800). The backend evaluates it against now() at run time, so the report stays current as it ages.