Report Generators
Developer guide for the Enezaframework reporting engine. Part of the Add Report series.
Table of Contents
- Overview
- Generator Map
- The Generator Contract
- TabularReportGenerator
- DocumentReportGenerator
- DrillDownReportGenerator
- Using Generators Directly
- Related Guides
Overview
Generators do the imperative work: fetch data, aggregate, format, and return a structured
response. The unified *ReportView base instantiates the right generator for your report
type automatically, but generators are plain classes you can also use from a management
command, API endpoint, or background task.
Generator Map
| Generator | Module | Report base |
|---|---|---|
TabularReportGenerator |
enezareporting.generators.tabular |
TabularReportView (+ SummaryReportView, DetailedReportView) |
CrosstabReportGenerator |
enezareporting.generators.crosstab |
CrosstabReportView |
TimeSeriesReportGenerator |
enezareporting.generators.time_series |
TimeSeriesReportView |
DocumentReportGenerator |
enezareporting.generators.document |
DocumentReportView |
DrillDownReportGenerator |
enezareporting.generators.drilldown |
DrillDownReportView |
CrosstabReportGenerator and TimeSeriesReportGenerator subclass
TabularReportGenerator, so the tabular methods below apply to them as well.
ListViewReportGenerator (also in generators/tabular.py) backs the legacy list view.
flowchart LR
TAB["TabularReportGenerator"] --> CROSS["CrosstabReportGenerator"]
TAB --> TS["TimeSeriesReportGenerator"]
TAB --> LIST["ListViewReportGenerator"]
DOC["DocumentReportGenerator"]
DD["DrillDownReportGenerator"]The Generator Contract
A generator returns a response shaped as:
{
"data": [...], # rows, or a document dict for DocumentReport
"columns": [...], # column metadata
"metadata": {...}, # totals, stats, extra info
"chart_settings": [...], # chart configuration
}
The view consumes this and passes it to the template. See Report Templates.
TabularReportGenerator
enezareporting.generators.tabular.TabularReportGenerator
from enezareporting.generators.tabular import TabularReportGenerator
gen = TabularReportGenerator(
report_model=SalesLine,
columns=["item_description", "__total__"],
group_by="item_code",
start_date=start,
end_date=end,
date_field="date_placed",
)
data = gen.get_report_data() # list of row dicts
columns = gen.get_columns_data() # column metadata
full = gen.get_full_response() # {data, columns, metadata, chart_settings}
DocumentReportGenerator
enezareporting.generators.document.DocumentReportGenerator
from enezareporting.generators.document import DocumentReportGenerator
gen = DocumentReportGenerator(
header_model=Invoice,
lines_related_name="lines",
header_fields=["invoice_number", "customer"],
line_columns=["item", "quantity", "line_total"],
line_total_fields=["line_total"],
)
result = gen.get_report_data(document_id=42)
# result = {
# "header": {"invoice_number": {"label": "Invoice #", "value": "INV-001"}, ...},
# "lines": [{"item": "Widget", "quantity": 5, "line_total": 100}, ...],
# "totals": {"line_total": 350},
# }
fetch_document raises ImproperlyConfigured when header_model is not set
(enezareporting/generators/document.py:67-84).
DrillDownReportGenerator
enezareporting.generators.drilldown.DrillDownReportGenerator
from enezareporting.generators.drilldown import DrillDownReportGenerator
from enezareporting.report_types import HierarchyLevel
gen = DrillDownReportGenerator(
hierarchy=[
HierarchyLevel(model=Region, display_field="name"),
HierarchyLevel(model=Branch, display_field="name", parent_field="region"),
],
)
root = gen.get_report_data(level_index=0) # root level
child = gen.get_report_data(level_index=1, path_ids=[1]) # children of region 1
can_drill = gen.can_drill_down(level_index=0, row_id=1)
Using Generators Directly
Generators are usable outside views — for example in a management command or export job:
from datetime import datetime
from enezareporting.generators.tabular import TabularReportGenerator
from myapp.models import SalesLine
def export_sales_report():
gen = TabularReportGenerator(
report_model=SalesLine,
columns=["item_description", "__total__"],
start_date=datetime(2024, 1, 1),
end_date=datetime(2024, 12, 31),
date_field="date_placed",
)
return gen.get_report_data()