Migrating to Unified Report Views

Developer guide for the Enezaframework reporting engine. Part of the Add Report series.

Table of Contents

  1. Overview
  2. Before and After
  3. Key Changes
  4. Computation Fields
  5. Backward Compatibility
  6. Related Guides

Overview

The legacy ReportView API still works, but new reports should inherit one unified *ReportView base. The migration is mechanical: rename the base class, declare a parameter_spec, and prefer registered computation field names over inline ComputationField.create(...) calls.

flowchart LR
    subgraph Legacy
        RV["ReportView"] --> FK["Form auto-built from FK fields"]
        RV --> CF["ComputationField.create(Sum, ...)"]
    end
    subgraph New
        RT["TabularReportView"] --> PS["parameter_spec = ParameterSet(...)"]
        RT --> REG["Registered name: '__total__'"]
    end
    RV -. migrate .-> RT
    OLD["TabularReport + ReportEngineView"] -. deprecated .-> RT

Before and After

Before (legacy API):

python
from enezareporting.views import ReportView
from enezareporting.fields import ComputationField
from django.db.models import Sum
from myapp.models import SalesLine


class SalesReport(ReportView):
    report_model = SalesLine
    date_field = "date_placed"
    group_by = "item_code"
    columns = [
        "item_description",
        ComputationField.create(Sum, "value", name="total_sales", verbose_name="Total Sales"),
    ]

After (unified API):

python
from enezareporting.report_base import TabularReportView
from enezareporting.parameters import ParameterSet, DateRangeParam, FKFilterParam
from myapp.models import SalesLine


class SalesReport(TabularReportView):
    report_model = SalesLine
    date_field = "date_placed"
    group_by = "item_code"
    columns = [
        "item_description",
        "__total__",  # registered computation field name
    ]
    parameter_spec = ParameterSet(
        DateRangeParam(name="date_range", start_field="date_placed"),
        FKFilterParam(name="customer", model_field="customer"),
    )

Key Changes

Old New
Inherit ReportView Inherit a unified *ReportView base.
Inherit TabularReport, ReportEngineView Inherit TabularReportView (deprecated form still works).
Form auto-built from FK fields Form built from parameter_spec.
ComputationField.create(Sum, "value", ...) Use a registered name such as "__total__", or import/define the field class.
No parameter declaration Declare parameter_spec = ParameterSet(...).
Form factory only Unified template + type-specific context.
DesignTemplateMixin first in MRO Set design_slug on the unified base.
TabularReportTotalsMixin Set add_totals = True and totals attributes.

Computation Fields

Registered computation fields can be referenced by name (enezareporting/fields.py):

python
columns = ["__total__", "__balance__", "__debit__", "__credit__"]

Define a custom field class, or create one on the fly:

python
from enezareporting.fields import ComputationField
from django.db.models import Sum, Avg


class AvgOrderValue(ComputationField):
    name = "__avg_order__"
    verbose_name = "Avg Order Value"
    calculation_method = Avg
    calculation_field = "value"


TotalWeight = ComputationField.create(
    Sum,
    "weight",
    name="total_weight",
    verbose_name="Total Weight",
)

ComputationField.create requires a unique name (enezareporting/fields.py:75-102).


Backward Compatibility

All existing classes continue to work:

  • ReportView, ModalReportView, ListReportView — unchanged.
  • ReportEngineView — unchanged; the old ReportType + ReportEngineView form is deprecated but still functional.
  • DesignTemplateMixin, TabularReportTotalsMixin — unchanged compatibility shims.
  • ReportGenerator, ListViewReportGenerator — unchanged.
  • ReportGeneratorAPI, Chart — unchanged.
  • ComputationField, field_registry — unchanged.
  • All existing template paths and tag names — unchanged.

See Report Views for the unified and legacy view tables.