0

I have a very similar problem to this question, Python datastructures into js datastructures using Django templates (lists and dicts) but with the next step - how do the variable names in python that are strings become javascript objects?

So in python I have this:

data = [{'year': 2006, 'books': 54, 'author': 'fred'},
    {'year': 2007, 'books': 43, 'author': 'sue'},
    {'year': 2008, 'books': 41, 'author': 'bill'},
    {'year': 2009, 'books': 44, 'author': 'alex'},
    {'year': 2010, 'books': 35, 'author': 'fred'}]

which I can output into my javascript via {{ data | safe }}

but I would like my javascript to look like this:

var data = [{year: 2006, books: 54, author: 'fred'},
    {year: 2007, books: 43, author: 'sue'},
    {year: 2008, books: 41, author: 'bill'},
    {year: 2009, books: 44, author: 'alex'},
    {year: 2010, books: 35, author: 'fred'}];

whereas it comes out at the moment like this:

var data = [{'year': 2006, 'books': 54, 'author': 'fred'},
    {'year': 2007, 'books': 43, 'author': 'sue'},
    {'year': 2008, 'books': 41, 'author': 'bill'},
    {'year': 2009, 'books': 44, 'author': 'alex'},
    {'year': 2010, 'books': 35, 'author': 'fred'}];

Is there anyway to do this?

Many thanks, Mark

4
  • stackoverflow.com/questions/19451017/… may help Commented Apr 13, 2014 at 15:06
  • I think JSON.parse(data) would be fine for your need. Commented Apr 13, 2014 at 15:08
  • In general it's pretty easy to communicate these data structures -- JSON.stringify/JSON.parse on the client side, json.dumps/json.loads on the server. Commented Apr 13, 2014 at 15:09
  • Thanks for your guidence! I think I may have the incorrect syntax as I tried your suggestions such as JSON.parse in this fiddle but it doesn't work: jsfiddle.net/Bh8et/1 I also have tried lots of solutions with JSON.stringify before asking, but couldn't see how this creates the un-string vars. Commented Apr 13, 2014 at 15:21

2 Answers 2

2

The tojson filter included with Flask takes care of producing a valid Javascript subset that is also HTML safe:

var data = {{ data|tojson|safe }};

If you are not using Flask, then register a custom filter like:

import json

def tojson(obj):
    """Produce HTML-safe JSON"""
    return (json.dumps(obj)
                .replace(u'<', u'\\u003c')
                .replace(u'>', u'\\u003e')
                .replace(u'&', u'\\u0026')
                .replace(u"'", u'\\u0027'))
Sign up to request clarification or add additional context in comments.

9 Comments

@traceur: JSON is a full subset of JavaScript except for two codepoints that JSON allows but JS disallows. The default json.dumps() setup escapes these two codepoints.
@traceur: Why use a template then? You wouldn't ever use a closure compiler on a template, at best only on the output of a template.
Many thanks, I thought maybe a filter would be the way as that was suggested before, but wasn't using Flask. However, I've registered this filter and reloaded, and the data is still including strings - I used {{ dataChart|tojson|safe }} in the template which becomes this when rendered: [{"medium": "organic", "visits": 2059.0}, {"medium": "(none)", "visits": 379.0}, {"medium": "referral", "visits": 346.0}]
@Mark: JavaScript allows for keys to be enclosed in quotes as strings. {"medium": "referral"} is the same thing as {medium: "referral"}. It is perfectly fine to have those quotes.
@MartijnPieters but for some reason it didn't work in ChartJS chartjs.devexpress.com with quotes, I thought it should do to, but it refused and so this hunt for unquoted. Maybe its some way its set up with the library.
|
1

The solution was a combo of Martijn Pieters and traceur, thanks a lot :D

So working version of code is:

In Python:

data = [{'year': 2006, 'books': 54, 'author': 'fred'},
{'year': 2007, 'books': 43, 'author': 'sue'},
{'year': 2008, 'books': 41, 'author': 'bill'},
{'year': 2009, 'books': 44, 'author': 'alex'},
{'year': 2010, 'books': 35, 'author': 'fred'}]

....rest of code....

variables = {
    'data' : data
    }
template = JINJA_ENVIRONMENT.get_template('main.html')
self.response.write(template.render(variables))

Additional to above, I had to register a new filter for JSON for jinja2:

JINJA_ENVIRONMENT = jinja2.Environment(
  loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
  autoescape=True,
  extensions=['jinja2.ext.autoescape'])

def tojson(obj):
 """Produce HTML-safe JSON"""
  return (json.dumps(obj)
            .replace(u'<', u'\\u003c')
            .replace(u'>', u'\\u003e')
            .replace(u'&', u'\\u0026')
            .replace(u"'", u'\\u0027'))

JINJA_ENVIRONMENT.filters['tojson'] = tojson

...then in the HTML needed to call this filter to place it in the javascript, but also eval as per traceur's comment. (I don't really know why)

<script type="text/javascript">
  dataSource = eval('({{ data|tojson|safe }})')
  console.log(dataSource)
  ....do stuff with dataSource....
</script>

dataSource is now a js object, which is in correct format for my ChartJS visulisation.

Thanks a lot!

Comments

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.