Document Report URLs, Designer & Rendering
Developer guide for the Enezaframework reporting engine. Part of the Add Report series.
Table of Contents
- Overview
- URL Auto-Registration
- URL Naming
- Designer Integration
- Rendering Paths
- Reference
- Related Guides
Overview
DocumentReportView classes are auto-registered by the framework and can render either
through the standard document template or through a designer-created layout. This guide
covers URL generation, designer integration, the two rendering paths, and the reference
tables.
URL Auto-Registration
get_registered_urls() in enezaframework/utils.py dispatches on view_type. A class
with view_type = 'document_report' and a model generates:
elif view_type == 'document_report':
report_name = getattr(view_class, 'report_name', None)
if report_name:
url_name = f'{report_name}_report'
url_pattern = f'{report_name}_report/<str:pk>/'
else:
url_name = f'{model_name}_report'
url_pattern = f'{model_name}_report/<str:pk>/'
urlpatterns.append(
path(url_pattern, view_class.as_view(), name=url_name)
)
DocumentReportPageView sets view_type = 'document_report'
(enezareporting/views.py), and DocumentReportView inherits it through
BaseDocumentReport.
flowchart TD
CLASS["@auto_url_register<br/>DocumentReportView subclass"] --> UTILS["get_registered_urls(app_name)"]
UTILS --> TYPE{"view_type ==<br/>'document_report'?"}
TYPE -->|Yes| NAME{"report_name set?"}
NAME -->|Yes| RN["{report_name}_report"]
NAME -->|No| MN["{model_name}_report"]
RN --> PATTERN["path: {name}/<str:pk>/"]
MN --> PATTERN
PATTERN --> URLS["urlpatterns = [*dynamic_urls]"]URL Naming
report_name set? |
URL pattern | URL name |
|---|---|---|
Yes, "invoice" |
/myapp/invoice_report/<str:pk>/ |
myapp:invoice_report |
Yes, "tax_invoice" |
/myapp/tax_invoice_report/<str:pk>/ |
myapp:tax_invoice_report |
No (falls back to model_name) |
/myapp/invoice_report/<str:pk>/ |
myapp:invoice_report |
The pattern uses <str:pk>, not <int:pk> (enezareporting/views.py).
Designer Integration
Set design_slug on the view class to use a designer-created report layout:
from enezareporting.report_base import DocumentReportView
from enezaframework.utils import auto_url_register
from myapp.models import Invoice
@auto_url_register
class InvoiceDesignReportView(DocumentReportView):
model = Invoice
report_name = "invoice_design"
header_model = Invoice
header_fields = ["invoice_number", "customer", "date", "due_date", "status"]
lines_related_name = "lines"
line_columns = ["item_code", "description", "quantity", "unit_price", "line_total"]
line_total_fields = ["line_total", "quantity"]
design_slug = "invoice-pdf-layout"
DocumentReportView inherits DesignTemplateMixin (via BaseDocumentReport and
DocumentReportPageView), which provides:
get_design()— returns theReportDesignby slug, orNoneif not found/not set.render_to_response()— when a design exists, compiles viaReportDesignCompiler, paginates, and renders throughdesign_report.html.get_template_names()— returns the compiled template string or falls back to defaults.
DocumentReportPageView.get_design() also falls back to a ReportDesign matched by the
report class name (enezareporting/views.py).
DocumentReportPageView.render_to_response() extracts the lines list from the document
data dict before calling the designer compiler, which expects data as a flat list for
pagination.
When using
DesignTemplateMixindirectly, it must appear first in the MRO so itsget()andrender_to_response()win (enezareporting/views.py).DocumentReportPageViewalready handles this through its own inheritance.
Rendering Paths
flowchart TD
GET["get(pk) → _get_document_report_results()"] --> CHECK{"design_slug resolves<br/>to a ReportDesign?"}
CHECK -->|No| STD["Standard path:<br/>report.html → document_report.html"]
CHECK -->|Yes| DESIGN["Designer path:<br/>ReportDesignCompiler.compile_paginated_report()<br/>→ design_report.html (A4 pages)"]1. Without a Designer Template (default)
When design_slug is not set, DesignTemplateMixin.get_design() returns None and the
standard template renders:
report.html → document_report.html
The template receives:
document_header— dict of header field values.document_lines— list of line item dicts.document_totals— dict of total field values.is_document_report—True.
2. With a Designer Template
When design_slug resolves to a valid ReportDesign, the designer compiler handles
pagination:
get() → _get_document_report_results() → render_to_response()
→ DesignTemplateMixin.render_to_response()
→ ReportDesignCompiler.compile_paginated_report(data_rows)
→ design_report.html with paginated A4 pages
Reference
DocumentReportView API
| Attribute | Required | Default | Description |
|---|---|---|---|
model |
Yes | — | Django model for URL registration and header. |
header_model |
Yes | — | Same as model; document header model for the generator. |
header_fields |
Yes | — | Field name strings for the header grid. |
line_columns |
Yes | — | Field name strings for lines table columns. |
report_name |
No | model.__name__.lower() |
Custom URL name segment. |
lines_related_name |
No | "lines" |
Related name for the line items FK. |
line_total_fields |
No | [] |
Numeric fields summed in the footer. |
design_slug |
No | None |
ReportDesign.slug for a designer layout. |
print_actions Dict Format
| Key | Type | Required | Description |
|---|---|---|---|
name |
str |
Yes | Display name in the Print dropdown. |
icon |
str |
Yes | Icon filename (without extension) under the static icons/ folder. |
url |
str |
Yes | URL name — matches report_name + _report. |
URL Registration
report_name set? |
URL pattern | URL name |
|---|---|---|
| Yes | {report_name}_report/<str:pk>/ |
{report_name}_report |
| No | {model_name}_report/<str:pk>/ |
{model_name}_report |
Key Constraints
modelmust be set —get_registered_urls()requiresissubclass(view_class.model, Model).- Use
report_namefor distinct URLs when one model has multiple report views. lines_related_namemust match therelated_nameon the line model's FK to the header.- Print dropdown position: between Delete and Workflow buttons.
- Print actions use
hx-get(no confirmation), unlikeaction_list, which useshx-post. - Print action URLs are used verbatim — no
_actionsuffix is appended.