Highcharts is, in my opinion, one of the best JavaScript libraries to work with data visualization and charts out there. Even though Highcharts is open source, it’s a commercial library. It’s free for use in non-commercial applications though.
In this tutorial we are going to explore how to integrate it with a Django project to render dynamically generated charts. In relation to drawing the charts and rendering it to the client, all the hard work is done by Highcharts at the client side. The configuration and setup is pure JavaScript.
The main challenge here is on how to translate the data from your backend to a format that Highcharts will understand. This data may come from a database or an external API, and probably is represented as Python objects (like in a QuerySet), or simply be represented as Python dictionaries or lists.
Generally speaking, there are two ways to do it:
- Via the request/response cycle, using Python and the Django template engine to write the JavaScript code directly in the template;
- Via an async request using AJAX, returning the data in JSON format.
The first option is like a brute force and in many cases the easiest way. The second option requires a slightly complicated setup, but you will also benefit from the page loading speed and from the maintainability of the code.
Installation / Setup
Basically we just need to include the Highcharts library in our template and we are ready to go. You can either download and serve it locally or simply use their CDN:
Usage Scenario
Now we need some data. I thought that it would be fun to play with an existing dataset. The Titanic dataset is pretty famous one, and easy to access.
What I did here was loading the dataset (1300~ rows) into a model named Passenger
:
If you are familiar with data mining, data science, or machine learning probably you already know this data set. This dataset is usually used for learning purpose. It’s composed by the list of passengers of the famous RMS Titanic tragedy.
We won’t be doing anything smart with it, just querying the database and displaying the data using Highcharts.
Highcharts Basics
I won’t dive into deep details about Highcharts. The goal is to understand how to make Django and Highcharts talk. For details about how to do this or that with Highcharts, best thing is to consult the official documentation.
Here is a working example of a column chart using Highcharts:
The code above generates the following chart:
The basic structure here is:
Basic Example
The most straightforward way to do it is by writing directly in the template (which is not recommended).
Let’s write an query to display the number of survivors and deaths organized by ticket class.
views.py
The queryset above generates a data in the following format:
Then we could just write it in the template, inside the JavaScript tags:
ticket_class.html
This kind of strategy is not really a good idea because the code is hard to read, hard to maintain and it is too easy
to shoot in the foot. Because we are using Python to generate JavaScript code, we have to format it properly.
For example, the code {% if not forloop.last %}, {% endif %}
is to not append a comma (,) after
the last item of the array (otherwise the result would be [200, 119, 181,]
). The newest JavaScript versions are
forgiving and accepts an extra comma (like Python does), but older versions don’t, so it might cause problem in old
browsers. Anyway, the point is you have to make sure your Python code is writing valid JavaScript code.
A slightly better way to do it would be processing the data a little bit more in the view:
views.py
ticket_class_2.html
Here’s what we are doing: first run through the queryset and create three separate lists, append the values and do the
formatting. After that, use the json
module and dump the Python lists into JSON format. The result are Python strings
properly formatted as JSON data.
We have to use the safe
template filter to properly render the categories
because Django automatically escape
characters like '
and "
for safety reason, so we have to instruct Django to trust and render it as it is.
We could also do all the configuration in the backend, like this:
views.py
ticket_class_3.html
As you can see, that way we move all the configuration to the server side. But we are still interacting with the JavaScript code directly.
JSON Example
Now this is how I usually like to work with Highcharts (or any other JavaScript library that interacts with the server).
The idea here is to render the chart using an asynchronous call, returning a JsonResponse
from the server.
This time, we are going to need two routes:
urls.py
The json_example
URL route is pointing to a regular view, which will render the template which will invoke the
chart_data
view. This call can be automatic upon page load, or it can be triggered by an action (a button click
for example).
views.py
Here we can see the json_example
is nothing special, just returning the json_example.html
template, which we are
going to explore in a minute.
The chart_data
is the one doing all the hard work. Here we have the database query and building the chart
dictionary. In the end we return the chart data as a JSON object.
json_example.html
Here is where the magic happens. The div with id container
is where the chart is going to be rendered. Now, observe
that I included a custom attribute named data-url
. Inside this attribute I stored the path to the view that will be
used to load the chart data.
Inside the ajax call, we make the request based on the URL provided in the data-url
and instruct the ajax request
that we are expecting a JSON object in return (defined by the dataType
). When the request completes, the JSON
response will be inside the data
parameter in the success function. Finally, inside the success
function, we
render the chart using the Highcharts API.
This is extremely useful because now we can decouple all the JavaScript from our template. In this example we used a single file for simplicity, but nothing stops us now from saving the script tag content in a separate file. This is great because we are no longer mixing the Django template language with JavaScript.
The result is the following screen shot:
Conclusions
In this tutorial we explored the basics on how to integrate Highcharts.js with Django. The implementation concepts used in this tutorial can be applied in other charts libraries such as Charts.js. The process should be very similar.
Whenever possible, try to avoid interacting with JavaScript code using the Django Template Language. Prefer returning the data as JSON objects already processed and ready to use.
Usually when working with charts and data visualization the most challenging part is to squeeze the data in the format required to render the chart. What I usually do is first create a static example hardcoding the data so I can have an idea about the data format. Next, I start creating the QuerySet using in the Python terminal. After I get it right, I finally write the view function.
If you want to learn more, the best way is to get your hands dirty. Here’s something you can do:
- First study the format of the data by checking the titanic.csv file;
- Then examine the Passenger model class;
- Go to the Highcharts.js demo page and find a chart you want to implement;
- Clone the django-highcharts-example repository on GitHub and implement it.