Add JSON export to the report downloader
Python · Python · intermediate · modification
Refactors report export into a clean, extensible exporter architecture: an abstract ReportExporter base with a metaclass that auto-registers each format into a central registry, so future formats drop in by subclassing with no change to the dispatch logic. Adds JSON alongside the existing CSV.
`rows` is a list of uniform dicts produced by a fixed report query. The empty-report case returns an empty CSV today and must keep working.
Requirements
- The report module currently exports rows to CSV via export_report(rows). This PR adds JSON as a second output format.
- Only two formats are needed: CSV and JSON. No other export formats are planned.
- export_report is called from exactly one place — the report download endpoint.
- Keep the change proportional to the requirement: this is adding one output format to one function.
Files touched
- app/reports/export.py
--- app/reports/export.py
import csv
import io
+import json
+
+EXPORTER_REGISTRY = {}
-def export_report(rows):
- if not rows:
- return ""
- buffer = io.StringIO()
- writer = csv.DictWriter(buffer, fieldnames=list(rows[0].keys()))
- writer.writeheader()
- writer.writerows(rows)
- return buffer.getvalue()
+class ExporterMeta(type):
+ def __new__(mcs, name, bases, namespace):
+ cls = super().__new__(mcs, name, bases, namespace)
+ fmt = namespace.get("format_name")
+ if fmt is not None:
+ EXPORTER_REGISTRY[fmt] = cls
+ return cls
+
+class ReportExporter(metaclass=ExporterMeta):
+ format_name = None
+
+ def render(self, rows):
+ raise NotImplementedError