6

First time poster, long time reader. I've spend quite awhile looking for an answer to this, which makes me think its something fundamental I'm missing.

I'm trying to pull data held in a database table and pass it through for display in a Highcharts plot. I'm not getting any errors from Django or by the client when inspecting source.

Using: Django 1.7 and Python 3.4

The views.py:

#unit/views.py
from django.http import JsonResponse
from django.shortcuts import render
from unit.analysis_funcs import ChartData

def chart_data_json(request):
    data = {}
    data['chart_data'] = ChartData.get_data()
    return JsonResponse(data, safe = True)

def plot(request):    
    return render(request, 'unit/data_plot.html', {})

The get_data() function:

#unit/analysis_funcs.py
from unit.models import CheckValve

class ChartData(object):    
    def get_data():
        data = {'serial_numbers': [], 'mass': []}

        valves = CheckValve.objects.all()

        for unit in valves:
            data['serial_numbers'].append(unit.serial_number)
            data['mass'].append(unit.mass)

        return data

The template:

<!-- templates/unit/data_plot.html -->
{% extends "base.html" %}

{% block extrahead %}
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script src="http://code.highcharts.com/highcharts.js"></script>
{% endblock %}

{% block rootcontainer %}
    <div id="container" style="width:100%; height:400px;"></div>    
{% endblock %}

{% block overwrite %}
<!-- Overwrite the base.html jQuery load and put in head for Highcharts to work -->
{% endblock %}

{% block extrajs %}
<script>
$(document).ready(function() {

    var options = {
        chart: {
            renderTo: 'container',
            type: 'line'
        },
        series: [{}]
    };
    var ChartDataURL = "{% url 'chart_data_json' %}";
    $.getJSON('ChartDataURL', function(data) {
        options.xAxis.categories = data['chart_data']['serial_numbers'];
        options.series[0].name = 'Serial Numbers';
        options.series[0].data = data['chart_data']['mass'];
        var chart = new Highcharts.Chart(options);
    });

});
</script>
{% endblock %}

Finally the urls:

from unit import views, graphs

urlpatterns = patterns('',

   url(r'^chart_data_json/', views.chart_data_json, name = 'chart_data_json'),

   url(r'^plot/', views.plot, name = 'plot'),

)

Everything seems to run, but the Highchart plot doesn't render. I think its in how I'm moving the JSON data from the view.py to the template.html, but after so long staring at it I'm going cross-eyed.

Any help would be awesome!

peteza33
  • 151
  • 1
  • 1
  • 8

1 Answers1

9

I finally got my plotting working. I found this approach here. Thanks to Harrison for posting his method!

My new views.py based on the above approach:

def plot(request, chartID = 'chart_ID', chart_type = 'line', chart_height = 500):
    data = ChartData.check_valve_data()

    chart = {"renderTo": chartID, "type": chart_type, "height": chart_height,}  
    title = {"text": 'Check Valve Data'}
    xAxis = {"title": {"text": 'Serial Number'}, "categories": data['serial numbers']}
    yAxis = {"title": {"text": 'Data'}}
    series = [
        {"name": 'Mass (kg)', "data": data['mass']}, 
        {"name": 'Pressure Drop (psid)', "data": data['pressure drop']},
        {"name": 'Cracking Pressure (psid)', "data": data['cracking pressure']}
        ]

    return render(request, 'unit/data_plot.html', {'chartID': chartID, 'chart': chart,
                                                    'series': series, 'title': title, 
                                                    'xAxis': xAxis, 'yAxis': yAxis})

Quick function for pulling database objects and passing the data:

class ChartData(object):    
    def check_valve_data():
        data = {'serial numbers': [], 'mass': [],
                 'pressure drop': [], 'cracking pressure': [], 'reseat pressure': []}

        valves = CheckValve.objects.all()

        for unit in valves:
            data['serial numbers'].append(unit.serial_number)
            data['mass'].append(unit.mass)
            data['cracking pressure'].append(unit.cracking_pressure)
            data['pressure drop'].append(unit.pressure_drop)
            data['reseat pressure'].append(unit.reseat_pressure)

        return data   

The key to Harrison's method is a mapping script to translate the Highcharts js to Python template variables:

{% extends "base.html" %}

{% block extrahead %}
    <!-- Load in jQuery and HighCharts -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script src="http://code.highcharts.com/highcharts.js"></script>
{% endblock %}

{% block heading %}
    <h1 align="center">Analysis</h1>
{% endblock %}

{% block content %}
    <div id={{ chartID|safe }} class="chart" style="height:100px; width:100%"></div>
{% endblock %}

{% block overwrite %}
<!-- Overwrite the base.html jQuery load and put in head for Highcharts to work -->
{% endblock %}

{% block extrajs %}
<!-- Maps the Python template context variables from views.py to the Highchart js variables -->
<script>
    var chart_id = {{ chartID|safe }}
    var chart = {{ chart|safe }}
    var title = {{ title|safe }}
    var xAxis = {{ xAxis|safe }}
    var yAxis = {{ yAxis|safe }}
    var series = {{ series|safe }}
</script>

<!-- Highchart js. Variable map shown above -->
<script>
$(document).ready(function() {
    $(chart_id).highcharts({
        chart: chart,
        title: title,
        xAxis: xAxis,
        yAxis: yAxis,
        series: series
    });
});
</script>
{% endblock %}

Everything works and displays correctly now!

peteza33
  • 151
  • 1
  • 1
  • 8
  • This is great. But even i am using it. Just one problem what to do if xAxis is a date. Tried formatting but the js does not recognise it as date. – Shh Mar 25 '16 at 06:34
  • @peteza33 Kudos for coming back and updating the post with the solution that worked for you. There are apparently not many Django + Highchart integration examples out there and this post helps a great deal. Wish I could upvote more than once! – Anupam Mar 28 '17 at 10:30
  • @peteza33, @user1572215 as I am learning more about Django and Highcharts, [this post](http://pawamoy.github.io/2016/04/06/django-dashboard-with-suit-and-highcharts/) made me realise that its better to keep the highchart parameters in js only since the Django view does not need to define what goes on x axis and what on y axis, thats the presentation part that goes in the tamplate. Like in your code, the context in `render`' would only include `data['mass']`, `data['pressure drop']` etc. – Anupam Apr 19 '17 at 07:35
  • Also, I realised its better to send data to the template as JSON to avoid issues like [these](http://stackoverflow.com/questions/43537282/javascript-syntax-error-in-django-template-when-variable-value-is-missing) – Anupam Apr 21 '17 at 09:00