Using Highcharts with Django 1.6 and Bootstrap 3
I was looking for a library to create charts to use for my Django app about a week ago and a friend suggested to try Highcharts as he had heard good things about it from fellow Python/Django developers.
Highcharts is a charting library purely written in JavaScript. The charts look really pretty and interactive. Using the library is quite easy, too, thanks to the well written documentation with lots of examples. You can view a demo here and start playing with it right away.
Below is an example of how I set it up for my project, using JSON for the data. I use Twitter Bootstrap 3 also and the charts blend with it very nicely.
Let's try to recreate this line chart shown on my app's dashboard:
Step 1: Make sure you have jQuery and the Highcharts JavaScript files referenced in your template.
This is how I have mine setup:
templates/base.html
... <!-- JavaScript --> <!-- Placed at the end of the document so the pages load faster --> {% compress js %} <script src="{{ STATIC_URL }}jquery/jquery.min.js"></script> {% block extrajs %}{% endblock %} {% endcompress %} ...
templates\core\dashboard.html
{% extends 'base.html' %} ... {% block extrajs %} <script src="{{ STATIC_URL }}highcharts/js/highcharts.js"></script> <script src="{{ STATIC_URL }}highcharts/js/modules/exporting.js"></script> {% endblock %}
It's important here to make sure that the jQuery js file is loaded first before Highcharts' js. The exporting.jsfile is optional. Including this file will automatically put the extra option (the 3 small horizontal lines on the top right corner) on your charts to export the graphics to different image formats.
Step 2: Prepare and serve your data from a view in JSON format.
# glucoses/reports.py from datetime import datetime, timedelta import core from .models import Glucose class ChartData(object): ... @classmethod def get_avg_by_day(cls, user, days): now = datetime.now(tz=user.settings.time_zone).date() glucose_averages = Glucose.objects.avg_by_day( (now - timedelta(days=days)), now, user) data = {'dates': [], 'values': []} for avg in glucose_averages: data['dates'].append(avg['record_date'].strftime('%m/%d')) data['values'].append(core.utils.round_value(avg['avg_value'])) return data
# glucoses/views.py import json @login_required def chart_data_json(request): data = {} params = request.GET days = params.get('days', 0) name = params.get('name', '') if name == 'avg_by_day': data['chart_data'] = ChartData.get_avg_by_day( user=request.user, days=int(days)) return HttpResponse(json.dumps(data), content_type='application/json')
In this step, we have a reports.py module that generates the data in a format that Highcharts would accept. We created a dictionary with 2 objects to hold the list of dates and values.
In views.py, we read the parameters in a GET request, and based on those parameters we generate the response.
Step 3: Create the HTML element where the chart will be loaded and the JavaScript to create the chart.
... <div class="panel panel-default"> <div id="chart_panel" class="panel-body" style="width:100%;height:314px"></div> </div> ... <script type="text/javascript"> $(document).ready(function() { // Glucose Average by Day chart var avgByDayOptions = { chart: { renderTo: 'chart_panel', type: 'line', }, legend: {enabled: false}, title: {text: 'Average Glucose by Day'}, subtitle: {text: 'Last 14 Days'}, xAxis: {title: {text: null}, labels: {rotation: -45}}, yAxis: {title: {text: null}}, series: [{}], }; var chartDataUrl = "{% url 'chart_data_json' %}?name=avg_by_day" + "&days=14"; $.getJSON(chartDataUrl, function(data) { avgByDayOptions.xAxis.categories = data['chart_data']['dates']; avgByDayOptions.series[0].name = 'Avg Glucose (mg/dL)'; avgByDayOptions.series[0].data = data['chart_data']['values']; var chart = new Highcharts.Chart(avgByDayOptions); }); } ); </script>
As you can see here, we first created a panel with an id 'chart_panel' to reference where the chart will be loaded to. The class names came from the Bootstrap CSS. The width and height are optional, but if specified, Highcharts will inherit those attributes.
Now on the JavaScript side, you'll see that the options are pretty simple. Highcharts has a lot more options as you can see here, but I just needed the basic ones. For example, you can specify whether to enable the legend, labels for x and y axes, etc.
When the template is loaded, the chart will load the data via a JSON call from the specified URL and creates the chart. Notice how the URL parameters match the ones in the view. The chart will be rendered to the panel that has the id 'chart_panel' as specified in the renderTo option.
That's pretty much it for the basics. If you'd like to learn more you can check out the General Documentation page which gives a more detailed explanation. You can also check out my project on GitHub for the complete implementation.
Tags: howto, python, twitter bootstrap, tech, javascript, highcharts