I am using Bottle web framework to render webpages. I am using bottle template engine to pass the variables from Python and then process them accordingly in the template file, which has embedded Python code.
Now the problem comes when I use javascript
within my template. If I try to access my Python variable inside the javascript
function, it fails with TypeError: unhashable type: 'list'
I am calling my template in my python file:
list_vals = [['Mushrooms', 3, 5], ['Onions', 1, 4], ['Olives', 1, 5], ['Zucchini', 1, 2]]
return bottle.template(os.path.join(os.path.dirname(__file__), 'templates', 'pizzaStats.html'), vals=list_vals)
In my template file I am using the vals
variable currently just to print inside the javascript, as shown below (just the script part of the template is shown):
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
// Create the data table.
var data = new google.visualization.DataTable();
%print ({{ vals }})
var graphdata = {{ vals }};
data.addColumn('string', 'Topping');
data.addColumn('number', 'Slices');
data.addColumn('number', 'pieces');
data.addRows(graphdata);
// Set chart options
// to smoothen the lines - 'curveType':'function'
var options = {'title':'How Much Pizza I Ate Last Night',
'width':400,
'height':300};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
Even if I change the type of the variable from list
to dict
type, it still complains. TypeError: unhashable type: 'dict'
The error is coming from the print()
but if I remove the print()
nothing happens and no graph is drawn, meaning the variable is not correctly assigned.
The end goal is to assign this variable to a javascript variable which will then plot the graph using Google APIs. What is the correct way to assign a Python variable to a javascript variable inside the bottle template? Thanks.
I think the problem is in the template side, when you render the vals
argument. The rendered vals
must be valid JavaScript code. By default, bottle auto-escapes HTML special characters, being single and double quotes among them. So, when you pass the Python list_vals
list to the template
function, it is evaluated to a string like this:
"[['Mushrooms', 3, 5], ['Onions', 1, 4], ['Olives', 1, 5], ['Zucchini', 1, 2]]"
and automatically escaped by bottle afterwords like this:
[['Mushrooms', 3, 5], ['Onions', 1, 4], ['Olives', 1, 5], ['Zucchini', 1, 2]]
producing an invalid JavaScript code.
The quick solution could be just disabling the bottle auto-escaping simply adding an exclamation mark to the template vals
parameter:
var graphdata = {{!vals}};