Skip to content

Report

The report app is designed to provide a simple and flexible way to create printable reports within Django Spire applications.

Key features include: - Easy report class for creation and customization. - Support for dynamic data sources and filters. - Integration with Django Spire's authentication and authorization system.

Installation

Simple add the django_spire.metric.report application to your INSTALLED_APPS and the DJANGO_SPIRE_REPORT_REGISTRIES to your settings:

settings.py
INSTALLED_APPS = [
    ...
    'django_spire.metric.report',
    ...
]

# this will be a list of ReportRegistry class module paths to be loaded
DJANGO_SPIRE_REPORT_REGISTRIES = []

You also need to add django spire to your projects urls.py:

urls.py
from django.urls import path, include

urlpatterns = [
    path('django_spire/', include('django_spire.urls', namespace='django_spire')),
]

Usage

Create a link to the report app in your project's navigation or menu using the url django_spire:metric:report:page:report.

Next create the report you want to generate. This can be done by defining a report class that inherits from django_spire.metric.report.report.BaseReport and implementing the necessary methods for data retrieval and report generation.

Example:

test_project/apps/queryset_filtering/reports/task_counting_monthly_report.py
import random
from datetime import date, datetime
from time import sleep

from django_spire.metric.report import BaseReport

NAMES = ['tom', 'jerry', 'sally', 'bob', 'alice']


class TaskCountingMonthlyReport(BaseReport):
    title: str = 'Task Counting Monthly Report'
    description = 'A broken down list of all the tasks completed monthly by user.'

    @staticmethod
    def person_choices():
        return (
            (i, name) for i, name in enumerate(NAMES)
        )

    def other_people_choices(self):
        return self.person_choices()

    def run(
            self,
            start_date: date = BaseReport.helper.start_of_last_month,
            end_datetime: datetime = BaseReport.helper.end_of_current_year,
            task_limit: int = 100,
            quality_limit: float = 20.0,
            show_puppets: bool = True,
            person: int = 0,
            other_people: list[int] = [0],
    ):
        sleep(1.0) # Simulate loading!

        self.add_column(f'People', sub_title=str(end_datetime))
        self.add_column('Type', type=self.ColumnType.CHOICE)
        self.add_column('Quality', type=self.ColumnType.PERCENT)
        self.add_column('Tasks', type=self.ColumnType.NUMBER)
        self.add_column('Hours', type=self.ColumnType.NUMBER_1)
        self.add_column('Days', type=self.ColumnType.NUMBER_2)
        self.add_column('Weeks', type=self.ColumnType.NUMBER_3)
        self.add_column('Value', type=self.ColumnType.DOLLAR)

        types = ['bug', 'feature', 'enhancement', 'documentation']

        self.add_divider_row('Main Tasks', description=f'This section shows the main task! {person=} and {other_people=}')

        for _ in range(1, 60):
            self.add_row([
                random.choice(NAMES),
                random.choice(types),
                random.randint(0, 100),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(100_000, 1_999_999),
            ], cell_sub_values=[
                start_date,
                None,
                None,
                None,
                None,
                None,
                None,
                'Tacos',
            ])

        self.add_divider_row('Internal Tasks', page_break=True)

        for _ in range(1, 20):
            self.add_row([
                random.choice(NAMES),
                random.choice(types),
                random.randint(0, 100),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(100_000, 1_999_999),
            ],
                border_top=True, border_bottom=True,
            )

        self.add_divider_row('Extra Tasks', page_break=True)

        for _ in range(1, 20):
            self.add_row([
                random.choice(NAMES),
                random.choice(types),
                random.randint(0, 100),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(10, 99),
                random.randint(100_000, 1_999_999),
            ])

        self.add_footer_row([
            'Totals:',
            '-',
            random.randint(30, 60),
            random.randint(30, 70),
            random.randint(30, 70),
            random.randint(30, 70),
            random.randint(30, 70),
            random.randint(5_000_000, 9_999_999),
        ])

        self.add_blank_row()
        self.add_blank_row(text='This some extra information on how tasks are evaluated and make sure to take time to read this and be amazed!!!')
        self.add_blank_row()

After we complete our report we want to create a registry so all reports in this app are together

Example:

test_project/apps/queryset_filtering/reports/task_report_registry.py
from django_spire.metric.report import ReportRegistry
from test_project.apps.queryset_filtering.reports.sub_task_report_registry import SubTaskReportRegistry

from test_project.apps.queryset_filtering.reports.task_counting_monthly_report import TaskCountingMonthlyReport

class TaskReportRegistry(ReportRegistry):
    category = 'Queryset Tasks'
    report_names_classes = {
            'Counting Monthly': TaskCountingMonthlyReport,
            'Counting Monthly Again': TaskCountingMonthlyReport
    }
    report_registries = [
        SubTaskReportRegistry
    ]

The final step is to add the registry to our settings file so it automatically adds to the page view.

settings.py
# Report Registry
DJANGO_SPIRE_REPORT_REGISTRIES = [
    'test_project.apps.queryset_filtering.reports.task_report_registry.TaskReportRegistry'
]

All done, we will now see our report in the sub navigation of the report app and be able to print.