11

If you use Django or Jinja2, you've probably ran into this problem before. I have a JSON string that looks like this:

{
  "data":{
    "name":"parent",
    "children":[
      {
        "name":"child_a",
        "fav_colors":[
          "blue",
          "red"
        ]
      },
      {
        "name":"child_b",
        "fav_colors":[
          "yellow",
          "pink"
        ]
      }
    ]
  }
}

Now I want to pass this to my Jinja2 template:

j = json.loads('<the above json here>')
self.render_response('my_template.html', j)

...and iterate it like this:

<select>
{% for p in data recursive %}
        <option disabled>{{ p.name }}</option>
        {% for c in p.children %}
            <option value="{{ c.fav_colors|safe }}">{{ c.name }}</option>
        {% endfor %}
{% endfor %}
</select>

This is where I'm having the problem: everything works except Jinja2 outputs unicode encoded values for c.fav_colors. I need c.fav_colors as a valid javascript array so that I can access it from javascript. How can I get Jinja to print that value as ascii text like: ['blue','red'] instead of [u'blue', u'red'] ?

2
  • 1
    No </option> closing tag ? Also, why not [{% for item in c %}"item"{% if not forloop.last %},{% endif %}{% endfor %}] ? This is what templates are for after all: converting python values into whatever needs the view. Commented Jan 4, 2012 at 13:10
  • Updated that option tag. The loop syntax I'm using here is for clarity. I'm just trying to showcase the problem: how to output c.fav_colors as valid javascript compatible array: ['blue','red'] Commented Jan 4, 2012 at 13:17

2 Answers 2

17

You need to convert the fav_colors list back to JSON. Probably the easiest way to do this would be with a quick template filter:

@register.filter
def to_json(value):
    return mark_safe(simplejson.dumps(value))

So now you could do

<option value="{{ c.fav_colors|to_json }}">
Sign up to request clarification or add additional context in comments.

4 Comments

duh! of course. but I'm actually using Jinja2 with webapp2 so now I need to find out how to do '@register.filter' part for Jinja.
Thank you. I can't believe I didn't think of that :-)
If anybody's wondering how I did this in webapp2: just lookup Jinja2 in webapp2 docs, then do something like this in the BaseHandler class: j=jinja2.get_jinja2(app=self.app) j.environment.filters.update({'to_json': to_json})
I had to use escape(mark_safe(simplejson.dumps(value))) in order to make it work. I was using this as part of the data attribute of li element in HTML and dynatree would not parse it correctly if I don't use escape.
3

Jinja2 now has a tojson() filter built-in https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-filters.tojson

{{ my_dict|tojson }}

Might not be exactly what OP (or another reader) needs, but worth mentioning here.

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.