0

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.

2
  • What happens if you send the string representation of the list? Like: return bottle.template(os.path.join(os.path.dirname(file), 'templates', 'pizzaStats.html'), vals=str(list_vals)) Commented Dec 9, 2014 at 7:55
  • @Rob then I get TypeError: unhashable type: 'set' Commented Dec 9, 2014 at 7:59

1 Answer 1

2

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:

[[&#039;Mushrooms&#039;, 3, 5], [&#039;Onions&#039;, 1, 4], [&#039;Olives&#039;, 1, 5], [&#039;Zucchini&#039;, 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}};
Sign up to request clarification or add additional context in comments.

1 Comment

Yes you are right. I was stuck at the print() and wondering why this error. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.