Skip to content

Commit 4025266

Browse files
committed
Merge branch 'release/0.5.0'
2 parents 2d7ea7b + ed02b81 commit 4025266

28 files changed

+1107
-241
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4+
## [0.5.0] - 2020-12-11
5+
6+
- Created the demo site https://django-slick-reporting.com/
7+
- Add support to group by date field
8+
- Add `format_row` hook to SlickReportingView
9+
- Add support for several chart engine per same report
10+
- Add `SLICK_REPORTING_FORM_MEDIA` &`SLICK_REPORTING_DEFAULT_CHARTS_ENGINE` setting.
11+
- Documenting SlickReportView response structure.
12+
- Fix issue with special column names `__time_series__` and `__crosstab__`
13+
_ Fix issue with Crosstab reminder option.
14+
15+
416
## [0.4.2] - 2020-11-29
517

618
- Properly initialize Datepicker (#12 @squio)

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ You can do a monthly time series :
101101
102102
# Analogy for time series
103103
time_series_pattern = 'monthly'
104-
time_series_columns = ['__total_quantity__']
104+
time_series_columns = [SlickReportField.create(Sum, 'quantity', name='sum__quantity') ]
105105
106106
107107
This would return a table looking something like this:

docs/source/computation_field.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Responsible for preforming the calculation.
88

99

1010
ReportField Basic Structure:
11-
----------------------
11+
----------------------------
1212

1313
Earlier in he docs you saw the computation fields ``'__total__quantity__'``
1414
Let's see how it's written in `slick_reporting.fields`
@@ -92,7 +92,7 @@ Two side calculation
9292

9393

9494
SlickReportField API
95-
-------------------
95+
--------------------
9696

9797
.. autoclass:: slick_reporting.fields.SlickReportField
9898

docs/source/customization.rst

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ The SlickReportView is a wrapper around FormView. It
2525
2. Form Customization
2626
---------------------
2727
Behind the scene, Sample report calls ``slick_reporting.form_factory.report_form_factory``
28-
a helper method which generates a form containing startdate and end date, as well as all foreign keys on the report_model.
28+
a helper method which generates a form containing start date and end date, as well as all foreign keys on the report_model.
2929

3030
The Form has exactly 2 purposes
3131

@@ -49,3 +49,26 @@ Slick Reporting comes with only 2 settings that can manipulated from `settings.p
4949

5050
1. ``SLICK_REPORTING_DEFAULT_START_DATE``: Default to the beginning of this year
5151
2. ``SLICK_REPORTING_DEFAULT_END_DATE``: Defaults to the end of the current year.
52+
3. ``SLICK_REPORTING_FORM_MEDIA``: Controlling the media files required by the search form.
53+
It defaults to :
54+
55+
.. code-block:: python
56+
57+
SLICK_REPORTING_FORM_MEDIA = {
58+
'css': {
59+
'all': (
60+
'https://cdn.datatables.net/v/bs4/dt-1.10.20/datatables.min.css',
61+
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.css',
62+
)
63+
},
64+
'js': (
65+
'https://code.jquery.com/jquery-3.3.1.slim.min.js',
66+
'https://cdn.datatables.net/v/bs4/dt-1.10.20/datatables.min.js',
67+
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js',
68+
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js',
69+
'https://code.highcharts.com/highcharts.js',
70+
)
71+
}
72+
You can change them to point to your local static or a you see fit and/or remove the unused chart bundle.
73+
74+
4. ``SLICK_REPORTING_DEFAULT_CHARTS_ENGINE``: Controls the default chart engine used. supports 'chartsjs' and 'highcharts' by default

docs/source/index.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Django Slick Reporting
33
======================
44

5-
**Django Slick Reporting** is a report engine that allows you to compute and create diverse report form with custom calculations
5+
**Django Slick Reporting** is a report engine that where you can create & display diverse analytics. Batteries like a ready to use View and Charts.js integration are included.
66

77

88
Installation
@@ -12,7 +12,7 @@ To install django-slick-reporting:
1212

1313
1. Install with pip: ``pip install django-slick-reporting``.
1414
2. Add ``'slick_reporting'`` to ``INSTALLED_APPS``.
15-
3. For the shipped in View, add ``'cirspy_forms'`` to ``INSTALLED_APPS``and add `CRISPY_TEMPLATE_PACK = 'bootstrap4'`
15+
3. For the shipped in View, add ``'crispy_forms'`` to ``INSTALLED_APPS``and add `CRISPY_TEMPLATE_PACK = 'bootstrap4'`
1616
to your `settings.py`
1717
1818
@@ -65,6 +65,7 @@ Neat huh ? Next step :ref:`usage`
6565

6666
tour
6767
customization
68+
view_response_structure
6869
report_generator
6970
computation_field
7071

docs/source/recipes.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.. _recipes:
2+
3+
Recipes
4+
=======
5+
6+
Remove a field from the generated Filter Form
7+
----------------------------------------------
8+
9+
10+
Alter the format for end results
11+
---------------------------------
12+
13+
Like showing a properly formatted date instead of the ISO.
14+
15+
16+
Add fields to the the generated report form
17+
-------------------------------------------
18+
19+

docs/source/tour.rst

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
.. _usage:
22

3-
Usage
4-
=====
3+
Concept
4+
=======
55

66

7-
I recon that you already have a model where there are data stored, and you want to generate reports on it.
8-
Let's say we have a a data similar to this
7+
Given that you have a model where there are data stored which you want to generate reports on.
8+
Consider below SalesOrder model example.
99

1010
+------------+------------+-----------+----------+-------+-------+
1111
| order_date | product_id | client_id | quantity | price | value |
@@ -19,12 +19,38 @@ Let's say we have a a data similar to this
1919
| 2019-03-14 | 1 | 2 | 3 | 15 | 45 |
2020
+------------+------------+-----------+----------+-------+-------+
2121

22-
Based on this data we can have several kind of reports, let's explore them one by one.
22+
Slick Reporting help us answer some questions, like:
23+
24+
* To start: Wouldn't it be nice if we have a view page where we can filter the data based on date , client(s) and or product(s)
25+
* How much each product was sold or How much each Client bought? Filter by date range / client(s) / product(s)
26+
* How well each product sales is doing, monthly?
27+
* How client 1 compared with client 2, compared with the rest of clients, on each product sales ?
28+
* How many orders were created a day ?
29+
30+
To answer those question, We can identify basic kind of alteration / calculation on the data
31+
2332

2433
1. Basic filtering
2534
------------------
2635

27-
A report where it displays the data as is. however we can apply date and other filters
36+
Start small,
37+
A ReportView like the below
38+
39+
.. code-block:: python
40+
41+
# in your urls.py
42+
path('path-to-report', TransactionsReport.as_view())
43+
44+
# in your views.py
45+
from slick_reporting.views import SlickReportView
46+
47+
class TransactionsReport(SlickReportView):
48+
report_model = MySalesItem
49+
columns = ['order_date', 'product__name' , 'client__name', 'quantity', 'price', 'value' ]
50+
51+
52+
will yield a Page with a nice filter form with
53+
A report where it displays the data as is but with filters however we can apply date and other filters
2854

2955
+------------+---------------+-------------+----------+-------+-------+
3056
| order_date | Product Name | Client Name | quantity | price | value |
@@ -38,23 +64,6 @@ A report where it displays the data as is. however we can apply date and other f
3864
| 2019-03-14 | Product 1 | Client 2 | 3 | 15 | 45 |
3965
+------------+---------------+-------------+----------+-------+-------+
4066

41-
This can be written like this
42-
43-
.. code-block:: python
44-
45-
# in your views.py
46-
from slick_reporting.views import SlickReportView
47-
48-
class TransactionsReport(SlickReportView):
49-
report_model = MySalesItem
50-
columns = ['order_date', 'product__name' , 'client__name', 'quantity', 'price', 'value]
51-
52-
# in your urls.py
53-
path('to-report', TransactionsReport.as_view())
54-
55-
Worth Noting here that the ``SlickReportView`` calls a form generator which return a form containing
56-
all foreign keys in the report_model + start and end date filter.
57-
5867
2. Group By report
5968
-------------------
6069

@@ -170,6 +179,8 @@ To create a report we need to a dictionary to a ``chart_settings`` to the SlickR
170179
171180
* type: what kind of chart it is: Possible options are bar, pie, line and others subject of the underlying charting engine.
172181
Hats off to : `Charts.js <https://www.chartjs.org/>`_.
182+
* engine_name: String, default to ``SLICK_REPORTING_DEFAULT_CHARTS_ENGINE``. Passed to front end in order to use the appropriate chart engine.
183+
By default supports `highcharts` & `chartsjs`.
173184
* data_source: Field name containing the numbers we want to plot.
174185
* title_source: Field name containing labels of the data_source
175186
* title: the Chart title. Defaults to the `report_title`.

docs/source/view.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
3+
columns
4+
5+
attribute
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
.. _view_response_structure:
2+
3+
SlickReportView Response Structure
4+
==================================
5+
6+
Understanding how the response is structured is imperative in order to customize how the report is displayed on the front end.
7+
8+
Let's have a look
9+
10+
.. code-block:: python
11+
12+
# Given a class like this
13+
class GroupByViewWith2Charts(SlickReportView):
14+
15+
report_model = SalesLineTransaction
16+
date_field = 'transaction_date'
17+
group_by = 'product'
18+
columns = ['name',
19+
SlickReportField.create(Sum, 'quantity', name='quantity__sum', verbose_name=_('Quantities Sold')),
20+
SlickReportField.create(Sum, 'value', name='value__sum', verbose_name=_('Value $')),
21+
]
22+
23+
chart_settings = [
24+
{'type': 'pie',
25+
'data_source': ['quantity__sum'],
26+
'title_source': ['name'],
27+
'title': 'Pie Chart (Quantities)'
28+
},
29+
{'type': 'bar',
30+
'engine_name': 'chartsjs',
31+
'data_source': ['value__sum'],
32+
'title_source': ['name'],
33+
'title': 'Column Chart (Values)'
34+
},
35+
]
36+
37+
# Ajax response or `report_results` template context variable.
38+
response = {
39+
# the report slug, defaults to all lower class name.
40+
"report_slug": "myreportviewclassname",
41+
42+
# a list of objects representing the actual results of the report
43+
"data": [
44+
{"name": "Product 0", "quantity__sum": "1774", "value__sum": "8758"},
45+
# .....
46+
],
47+
48+
# A list explaining the columns/keys in the data results.
49+
# ie: len(response.columns) == len(response.data[i].keys())
50+
# Contains needed information about the verbose name , if summable , hints about the data type.
51+
"columns": [
52+
{"name": "name",
53+
"computation_field": "",
54+
"verbose_name": "Name",
55+
"visible": True,
56+
"type": "CharField",
57+
"is_summable": False
58+
},
59+
{"name": "quantity__sum",
60+
"computation_field": "",
61+
"verbose_name": "Quantities Sold",
62+
"visible": True,
63+
"type": "number",
64+
"is_summable": True},
65+
{"name": "value__sum",
66+
"computation_field": "",
67+
"verbose_name": "Value $",
68+
"visible": True,
69+
"type": "number",
70+
"is_summable": True}
71+
],
72+
73+
# Contains information about the report as whole if it's time series or a a crosstab
74+
# And what's the actual and verbose names of the time series or crosstab specific columns.
75+
"metadata": {"time_series_pattern": "",
76+
"time_series_column_names": [],
77+
"time_series_column_verbose_names": [],
78+
"crosstab_model": '',
79+
"crosstab_column_names": [],
80+
"crosstab_column_verbose_names": []
81+
},
82+
83+
84+
# a mirror of the set charts_settings on the SlickReportView
85+
# SlickReportView populates the id if missing and fill the `engine_name' if not set
86+
"chart_settings": [
87+
{"type": "pie",
88+
'engine_name': 'highcharts',
89+
"data_source": ["quantity__sum"],
90+
"title_source": ["name"],
91+
"title": "Pie Chart (Quantities)",
92+
"id": "pie-0"},
93+
94+
{"type": "bar",
95+
"engine_name": "chartsjs",
96+
"data_source": ["value__sum"],
97+
"title_source": ["name"],
98+
"title": "Column Chart (Values)",
99+
"id": "bar-1"}
100+
]
101+
}
102+
103+

setup.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ name = django-slick-reporting
44
version = attr: slick_reporting.__version__
55
author = Ra Systems
66
author_email = ramez@rasystems.io
7-
description = A one-stop report adn analytics generation and computation with batteries included
7+
description = A one-stop report and analytics generation and computation with batteries included
88
long_description = file:README.rst
99
long_description_content_type = text/x-rst
10-
url = https://github.com/ra-systems/django-slick-reporting
10+
url = https://django-slick-reporting.com/
1111
project_urls =
1212
Travis CI = https://travis-ci.org/ra-systems/django-slick-reporting/
1313
Documentation = https://django-slick-reporting.readthedocs.io/en/latest/

slick_reporting/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
default_app_config = 'slick_reporting.apps.ReportAppConfig'
33

4-
VERSION = (0, 4, 2)
4+
VERSION = (0, 5, 0)
55

6-
__version__ = '0.4.2'
6+
__version__ = '0.5.0'

slick_reporting/app_settings.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,22 @@ def get_end_of_this_year():
1717

1818
SLICK_REPORTING_DEFAULT_START_DATE = getattr(settings, '', lazy(get_first_of_this_year, datetime.datetime)())
1919
SLICK_REPORTING_DEFAULT_END_DATE = getattr(settings, '', lazy(get_end_of_this_year, datetime.datetime)())
20+
21+
SLICK_REPORTING_FORM_MEDIA_DEFAULT = {
22+
'css': {
23+
'all': (
24+
'https://cdn.datatables.net/v/bs4/dt-1.10.20/datatables.min.css',
25+
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.css',
26+
)
27+
},
28+
'js': (
29+
'https://code.jquery.com/jquery-3.3.1.slim.min.js',
30+
'https://cdn.datatables.net/v/bs4/dt-1.10.20/datatables.min.js',
31+
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js',
32+
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js',
33+
'https://code.highcharts.com/highcharts.js',
34+
)
35+
}
36+
37+
SLICK_REPORTING_FORM_MEDIA = getattr(settings, 'SLICK_REPORTING_FORM_MEDIA', SLICK_REPORTING_FORM_MEDIA_DEFAULT)
38+
SLICK_REPORTING_DEFAULT_CHARTS_ENGINE = getattr(settings, 'SLICK_REPORTING_DEFAULT_CHARTS_ENGINE', 'highcharts')

slick_reporting/fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def create(cls, method, field, name=None, verbose_name=None, is_summable=True):
5959
"""
6060
if not name:
6161
identifier = str(uuid.uuid4()).split('-')[-1]
62-
name = name or f"__{method.name}_{field}_{identifier}__"
62+
name = name or f"{method.name}__{field}"
6363
assert name not in cls._field_registry.get_all_report_fields_names()
6464

6565
verbose_name = verbose_name or f'{method.name} {field}'

0 commit comments

Comments
 (0)