Reputation: 5844
I'm creating charts for my Django app using C3.js. In my Django template, I have a JavaScript snippet like this:
<script>
var chart = c3.generate({{ chart_data|safe }});
</script>
In the view, I set up the chart using a Python data structure, which is converted to JSON before being rendered by the template:
chart = {
'bindto': '#chart',
'data': {
'columns': [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
}
return render_to_response('chart.html', {'chart_data': json.dumps(chart)})
That works fine, and I get something like this example.
For more complicated C3 charts, I need to be able to include JavaScript functions in the argument to c3.generate. (For example the onclick
value in this donut chart.) But JSON doesn't support representing functions, and adding 'onclick': 'function (d, i) { ... };'
to the Python dict just results in a string when JSON encoded. Trying to subclass json.JSONEncoder
seems fruitless, as what I need to output isn't valid JSON, it's actual JavaScript.
Is there a neat way of doing this? At the moment I'm doing a kludgy workaround, inserting the JavaScript function code into the result of json.dumps()
.
Upvotes: 2
Views: 483
Reputation: 5844
On reflection, I think what I'm asking is a case of approaching the problem the wrong way, or using the wrong tools to solve the problem.
The data structure given to c3.generate()
contains two things:
There's no particular reason I need to have the configuration setup in the Django view code. With that realization, I can move the configuration (including the problematic "onclick" JavaScript function I wanted to add) to the template, and inject the data into a separate variable.
The template would be:
<script>
var columns = {{ chart_columns|safe }};
var chart = c3.generate({
bindto: '#chart',
data: {
columns: columns,
onclick: function (d, i) { /* ... */ }
}
});
</script>
And the view code:
chart = [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
return render_to_response('chart.html', {'chart_columns': json.dumps(chart)})
As well as solving my problem, this fits better with Django's Model-View-Template design.
Upvotes: 2