Skip to main content

Django Simple Charts

Learn how to showcase charts in Django

Django is a powerful web framework that allows developers to build complex web applications quickly and easily. One popular use case for Django is building data-driven web applications that display information in charts and graphs. In this tutorial, we will explore how to use Django and Chart.js together to build a web application that displays data in an interactive chart.

Before we get started, let's briefly introduce Chart.js. Chart.js is a JavaScript library that allows developers to create beautiful and responsive charts and graphs using HTML5 canvas. It provides a wide range of chart types, including line, bar, pie, radar, and more. Chart.js is easy to use and highly customizable, making it a popular choice for data visualization on the web.

In this tutorial, we will be making use of Django Material Dashboard, and we will be modifying its homepage to create sales charts using data from Django models.

To get started, we will first set up a new Django project and create a new app that will serve as the homepage of our application. We will then create a model to store our sales data and create a view to serve the data to our front-end.

Finally, we will use Chart.js to create an interactive bar chart, line chart and pie chart that displays data from the sales model.

Django Simple Charts - Tutorial provided by AppSeed.

✅ Setting up Django

You can create a new folder, change the directory into the new folder, and create a new virtual environment by running the following commands in the terminal:

To create a new folder, use the "mkdir" command followed by the name you want to give to the folder.

$ mkdir django-charts

To change the directory into the new folder, use the "cd" command followed by the name of the folder you just created.

$ cd django-charts

To create a new virtual environment, you can use the virtualenv module bundled with Python.

django-charts$ virtualenv venv

This will create a new virtual environment in a folder called "venv" inside your "django-charts" folder.

This command is used to activate the virtual environment

On MacOS/Linux

django-charts$ source venv/bin/activate
(venv) django-charts$

On Windows

(venv) django-charts$ ./venv/Scripts/activate
(venv) django-charts$

After activating the virtual environment, you can proceed to install the required packages. To install Django and material-design and also create a new Django project, run the following commands on your terminal.

(venv) django-charts$ pip install django django-admin-material-dashboard
(venv) django-charts$ django-admin startproject core .

Once the Django project has been created, the next step is to create a new Django application and modify the project to recognize the application and the material dashboard that was installed earlier.

  1. Create a new Django application by executing the command
(venv) django-charts$ python manage.py startapp home
  1. Open core/settings.py and make the following changes
# core/settings.py
import os # <-- NEW import
...
INSTALLED_APPS = [
"home",
"admin_material.apps.AdminMaterialDashboardConfig",
...
]
...
UI_TEMPLATES = os.path.join(BASE_DIR, "templates") # <-- NEW

TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [UI_TEMPLATES], # <-- UPDATED
...
}
]
...
STATIC_URL = "/static/"
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
LOGIN_REDIRECT_URL = '/'
...
  1. Make the following changes to core/urls.py to add routes to the application created and material dashboard
# core/urls.py
from django.urls import include, path <-- UPDATED add path

urlpatterns = [
path('', include('home.urls')),
path("admin/", admin.site.urls),
path("", include('admin_material.urls'))
]
  1. We will be creating a view to the homepage of the web application inside home/views.py.
# home/views.py
...
def index(request):

# Page from the theme
return render(request, 'pages/index.html')

  1. Create the file urls.py inside home folder and create a route to the index view created.
# home/urls.py
from django.urls import path

from . import views

urlpatterns = [
path('', views.index, name='index'),
]

Run the Django server from your terminal by executing the command

(venv) django-charts$ python manage.py runserver

From your browser, head to http://127.0.0.1:8000, this shows the theme installed. You will see the material dashboard theme. As we progress through this tutorial, we will learn how to utilize data from our Django models to make the charts dynamic.


✅ Create a new Model

The application already has static charts, to display dynamic sales data in our Django and Chart.js web application, we need to first create a model to store the data in our database.

Defining Model Schema

We will be using Django Object Relational Mapper to define the structure of the database. Open home/models.py and make the changes

# home/models.py
from django.db import models

class Sales(models.Model):
product = models.CharField(max_length=255)
price = models.IntegerField()
currency = models.CharField(
choices=(('USD', 'USD'), ('EUR', 'EUR')),
default='USD',
max_length=3
)
country = models.CharField(max_length=50)
purchase_date = models.DateTimeField()

def __str__(self):
return self.product

class Meta:
verbose_name = 'Sale'
verbose_name_plural = 'Sales'

Population the database with sales data

  • Now we need to register the database so we can access it from the admin panel. Make the following changes to home/admin.py
# home/admin.py
...
from .models import Sales # <-- NEW import

admin.site.register(Sales)
  • Stop your Django server using Ctrl + c and run the command to create Django default tables and the Sales table just created.
(venv) django-charts$ python manage.py makemigrations
(venv) django-charts$ python manage.py migrate
  • Next step we will be creating a superuser, this will enable us to have access to the admin panel
(venv) django-charts$ python manage.py createsuperuser
(venv) django-charts$ python manage.py runserver

With your browser visit http://127.0.0.1:8000/admin, You will see the sales table just created.

Admin dashboard showing sales model

  • Now you can use the add sale button from the admin panel to populate the database with data

Admin dashboard with populated data


✅ Using Chart.Js with Django

Installing Chart.js

There are several ways Chart.js can be used in a web development project. It can be done using CDN and using npm to install the chart.js package. Check chart.js installation guide for directions to install chart.js

Integrate Chart.js

We will be using the CDN method for this tutorial. Create a base template for inside your templates folder named base.html and add the code

<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% block javascript%}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.2.1/chart.min.js" integrity="sha512-v3ygConQmvH0QehvQa6gSvTE2VdBZ6wkLOlmK7Mcy2mZ0ZF9saNbbk19QeaoTHdWIEiTlWmrwAL4hS8ElnGFbA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
{% endblock %}
<title>Document</title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>

The {% block javascript %} contains a script to the chart.js cdn and this will provide the Classes needed to add charts to the web application.

NB: django-admin-material-dashboard already uses Chart.js, without defining our script, we can make use of it.

  • copy index.html file from venv/lib/python3.10/site-packages/admin_material/templates/pages and paste it into templates/pages. Now our index.html page for the application will be served by the file in templates/pages

✅ Creating charts with Chart.js

So far the charts have displayed static data hardcoded into it. Now we will be making the chart display values from the sales model.

Creating Bar chart with Chart.js

The bar chart to be created will be showing details of total sales made on every product.

  • Making changes to the index views to send data from the model as context to index.html. Open home/views.py` and make the changes
# home/views.py
...
import json

from .models import Sales

def index(request):
sales_query = Sales.objects.values('product', 'price', 'purchase_date')

total_sales_per_product = {}
for result in sales_query:
product_name = result['product']

# total sales by product
if total_sales_per_product.get(product_name):
total_sales_per_product[product_name] += result['price']
else:
total_sales_per_product[product_name] = result['price']

return render(request, 'pages/index.html', {
'sales_product': sales_product, 'labels_product': labels_product
})
  • Now changes will be made to the bar chart, so it displays information from the backend. The code for the bar chart is located at the bottom of the template. Make the following changes to templates/pages/index.html
    // templates/pages/index.html
...
var ctx = document.getElementById("chart-bars").getContext("2d");

new Chart(ctx, {
type: "bar", // <-- Type of chart
data: {
labels: {{ labels_product|safe }}, // <-- UPDATED to use labels from the backend
datasets: [{
label: "Sales",
data: {{ sales_product }}, // <-- UPDATED to use data from the backend
}, ],
},
...
});

labels_product|safe is done so the array is not HTML-escaped, because that will cause errors.

Creating Line chart with Chart.js

The line to be displayed is to show the total sales made on days of the week.

  • We will be making some changes to home/views.py and altering the index function
# home/views.py
...
def index(request):
...
total_sales_per_day = {}
for result in sales_query:
...
day = result['purchase_date'].strftime('%a')
...
# sales per day
if day in total_sales_per_day:
total_sales_per_day[day] += result['price']
else:
total_sales_per_day[day] = result['price']
...

# sales per day
key = {
'Mon': 1,
'Tue': 2,
'Wed': 3,
'Thur': 4,
'Fri': 5,
'Sat': 6,
'Sun': 7
}
days = sorted(total_sales_per_day, key=key.get) # sorting by days, so the result shows in order of days of the week
sales_day, labels_day = [], []
for k in days:
sales_day.append(total_sales_per_day[k])
labels_day.append(k)

return render(request, 'pages/index.html', {
'sales_product': sales_product, 'labels_product': labels_product,
'sales_day': sales_day, 'labels_day':labels_day, # <-- ADDED
})

You can checkout full code for home/views.py here

  • Now we will be making changes to templates/pages/index.html to display the information from the backend
// templates/pages/index.html
...
new Chart(ctx2, {
type: "line", // <-- chart type
data: {
labels: {{ labels_day|safe }}, // <-- UPDATED
datasets: [{
...
label: "Sales",
data: {{sales_day}}, // <-- UPDATED
}],
},
});
...

Creating a Pie chart with Chart.js

The pie chart to be added to the web page will be showing the sales distribution of each product. The Pie chart will utilize the same data as the bar chart added earlier. Below is the full code for home/views.py

# home/views.py

def index(request):
sales_query = Sales.objects.values('product', 'price', 'purchase_date')

total_sales_per_day = {}
total_sales_per_product = {}
for result in sales_query:
product_name = result['product']
day = result['purchase_date'].strftime('%a')

# sales per product
if total_sales_per_product.get(product_name):
total_sales_per_product[product_name] += result['price']
else:
total_sales_per_product[product_name] = result['price']


# sales per day
if day in total_sales_per_day:
total_sales_per_day[day] += result['price']
else:
total_sales_per_day[day] = result['price']

# sales per product
sales_product, labels_product = [], []
for k, v in total_sales_per_product.items():
sales_product.append(v)
labels_product.append(k)


# used for sorting days of the week
key = {
'Mon': 1,
'Tue': 2,
'Wed': 3,
'Thur': 4,
'Fri': 5,
'Sat': 6,
'Sun': 7
}
days = sorted(total_sales_per_day, key=key.get)
sales_day, labels_day = [], []
for k in days:
sales_day.append(total_sales_per_day[k])
labels_day.append(k)

# Page from the theme
return render(request, 'pages/index.html', {
'sales_product': sales_product, 'labels_product': labels_product,
'sales_day': sales_day, 'labels_day': labels_day,
})
  • Now we will be making some changes to templates/pages/index.html to include our pie chart.
{% comment %}
templates/pages/index.html

the first change to be made, will be done line 125 by updating the id of the canvas to `chart-pie`
{% endcomment %}
...
<canvas id="chart-pie" class="chart-canvas" height="170"></canvas>
...


var ctx3 = document.getElementById("chart-pie").getContext("2d"); <-- UPDATED to point to the updated id

new Chart(ctx3, {
type: "pie", // <-- UPDATED type of chart
data: {
labels: {{ labels_product|safe }}, // <-- UPDATED
datasets: [{
borderWidth: 2,
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)',
],
fill: true,
data: {{ sales_product }}, // <-- UPDATED
}],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
labels: {
color: 'rgb(255,255,255)',
font: {
size: 14,
weight: 300,
family: "Roboto",
style: 'normal',
lineHeight: 2
}
}
},
},
},
});

The pie chart contains lesser configuration because a lot of the details added by those configurations are not needed for the pie chart

admin_material dashboard with dynamic charts

We have added charts to our Django application, but there's a lot more configuration that can be added to our charts to change their look and feel, and also make them blend perfectly with our application. Chart.js contains detailed documentation on how to configure charts.

✅ Conclusion

In this tutorial, we've explored how to use Django and Chart.js together to build a web application that displays data in an interactive chart. We started by setting up a new Django project and app, creating a model to store our sales data, and populating the database with sample data.

By following this tutorial, you should now have a good understanding of how to use Django and Chart.js to build a data-driven web application that displays information in an interactive chart. You can use this knowledge to build your web applications and customize the chart to fit your specific use case.

✅ Resources