Bar Chart - Information is rendered after a data load (admin section)
HELP
Above chart is generated dinamically based on the information gathered by get_sales_report)(), a inner method defined by Sale model
To update the charts, please authenticate as admin, update the SALES table information and refresh the page.
Note: Admin account can be created using the createsuperuser command.
The Routing Settings
This page has a simple rule defined in the
app/urls.py file:
# Contents of file: app/urls.py
urlpatterns = [
...
# Charts from Input
path('charts-load' , views.charts_load, name='charts-load' ),
...
]
Render Flow
The code that render this page use the information from SALES table.
The model
comes with a inner method that selects all rows: get_sales_report().
Once the SALES rows are selected, controller read the page template and inject the information.
Source: app/views.py
- charts_load():
# Partial content from file: app/views.py
def charts_load(request):
context = {'segment': 'charts_from_load'}
html_template = loader.get_template('charts-from-load.html')
# -----------------------------------------------
# Extract data from Sale table
# -----------------------------------------------
sales, labels = Sale.get_sales_report()
data = [
{
'y': year,
'a': '{:.2f}'.format(sales[year].get('A')),
'b': '{:.2f}'.format(sales[year].get('B')),
'c': '{:.2f}'.format(sales[year].get('C'))
} for year in sales
]
context['chart_data'] = json.dumps({
'element': 'morris-bar-chart',
'data': data,
'xkey': 'y',
'barSizeRatio': 0.70,
'barGap': 3,
'resize': True,
'responsive': True,
'ykeys': ['a', 'b', 'c'], # it can be custom
'labels': labels,
'barColors': ['0-#1de9b6-#1dc4e9', '0-#899FD4-#A389D4', '#04a9f5'] # it can be custom
})
return HttpResponse(html_template.render(context, request))
Database Model - SALES
The model
comes with a inner method that selects all rows: get_sales_report().
class Sale(models.Model):
amount = models.FloatField(_('amount'), db_index=True)
product_name = models.CharField(_('product name'), max_length=40, db_index=True)
created_time = models.DateTimeField(verbose_name=_('creation On'), db_index=True)
updated_time = models.DateTimeField(verbose_name=_('modified On'), auto_now=True)
class Meta:
verbose_name = _('sale')
verbose_name_plural = _('sales')
@classmethod
def get_sales_report(cls):
annotates = {'total_amount': Sum('amount')}
sales = cls.objects.annotate(
year=TruncYear('created_time')
).values('product_name', 'year').order_by().annotate(**annotates)
data = {}
for sale in sales:
if sale['year'].year not in data:
data[sale['year'].year] = {}
data[sale['year'].year][sale['product_name']] = sale['total_amount']
labels = list(sales.values_list('product_name', flat=True).distinct())
return data, labels
HTML File
The chart data is rendered using Morris JS,
a popular open-source chart library.
The source file
core/templates/charts-from-load.html.