.. image:: https://img.shields.io/pypi/v/django-admin-reports.svg :target: https://pypi.python.org/pypi/django-admin-reports .. image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/psf/black
Overview
"admin_reports" is a Django application to easily create data aggregation reports to display inside Django admin.
The Django admin is very much centered on models and it provide a quick and simple way to create a GUI for the CRUD interface, but often there's the need to display data in an aggregate form, here's where admin_reports comes handy.
The idea is to have a class similar to ModelAdmin
(from
django.contrib.admin
) that allow to display derived data
concentrating on implementing the aggregation procedure.
Basic Usage
First of all add admin_reports
to your project's INSTALLED_APPS
settings
variable; it's important that it is after django.contrib.admin
.
Basically admin_reports provide your Django site with an abstract view
Report
. All you need to do is give an implementation to the
abstract method aggregate()
. The important thing is that this
method must return a list of dictionaries, a Queryset or a
pandas.Dataframe
(https://github.com/pydata/pandas).
A stupid example could be this: ::
from admin_reports import Report, register
@register() class MyReport(Report): def aggregate(self, **kwargs): return [ dict([(k, v) for v, k in enumerate('abcdefgh')]), dict([(k, v) for v, k in enumerate('abcdefgh')]),.. ]
Then in your django site urls.py
add the following: ::
from django.contrib import admin import admin_reports
urlpatterns = patterns( ... url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin_reports.site.urls)), ... )
The auto generate urls will be a lowercase version of your class name.
So for the example above::
/admin/myapp/myreport/
The urlname to be passed to reverse
will be the underscored
version of your class name, so with the above example::
'admin_reports:my_report'
aggregate
Most of the times you'll need to pass parameters to aggregate
, you
can do so by the association of a Form class to your Report: all the
form fields will be passed to aggregate
as keyword arguments, then
it's up to you what do with them.::
from django import forms from admin_reports import Report
class MyReportForm(forms.Form): from_date = forms.DateField(label="From") to_date = forms.DateField(label="To")
class MyReport(Report): form_class = MyReportForm
def aggregate(self, from_date=None, to_date=None, **kwargs):
# Write yout aggregation here
return ret
The Report class
The Report
class is projected to be flexible and let you modify
various aspect of the final report.
As for the ModelAdmin
the most straightforward way of changing the
behavior of your subclasses is to override the public class
attributes; anyway for each of these attributes there is a
get_<attr>
method hook to override in order to alter behaviors at
run-time.
This is a list of field names that you want to be used as columns in
your report, the default is None
and means that the get_fields
method will try to guess them from the results of your aggregate
implementation.
The fields
attribute can contain names of callables. This
methods are supposed to receive a record of the report as a
parameter.::
class MyReport(Report):
fields = [
...,
'pretty_value',
...
]
def pretty_value(self, record):
return do_something_fancy_with(record['my_column'])
For this callables the allow_tags
attribute can be set to True
if they are supposed to return an HTML string.
Fields labels ^^^^^^^^^^^^^
When a field name is provided alone in the fields
attribute
admin_reports
will generate a label for you in the rendered
table. If you want to provide a custom label just enter a tuple of two
elements instead of just the field name, (field_name, label)
.
The formatting
attribute is a dictionary that lets you specify the
formatting function to use for each field.::
class MyReport(Report):
formatting = {
'amount': lambda x: format(x, ',.2f'),
}
This attribute is a boolean to tell whether the last record of your aggregation is to be considered as a row of totals, in this case it will be displayed highlighted on every page.
Whether to display an eventual record of totals in on top of the
table, if False
it will be displayed on bottom.
This attribute has no effect if Report.has_totals
is False
.
A string to use as the page title.
A short description to explain the meaning of the report.
A longer description of the report, meant to explain the meaning of each single field.
The template to use to render the report as an html page (default:
admin/report.html
).
The class to use a Paginator
.
list_per_page
parameter passed to the Paginator
class.
list_max_show_all
parameter passed to the Paginator
class.
How to align values in columns when rendering the html table, a
dictionary that associates to each field one of the following values
(aling-left
, align-center
, align-right
).
The Form
class to use to pass parameter to the aggregate
method.
The Form
class to use to pass parameter to the to_csv
method.
Initial values for the form_class
.