Rendering a JSON string inside a script with Django

Building a list of form submissions in Django last night was causing me some issues. This is likely a common issue for people and something most people know already, but I wasn’t able to find a nice answer online after my searching, so here’s my solution for others to benefit from.

My scenario:

  • Build a list of submissions inside the view
  • Pass these into the template, so that Vue could render the details

I could have made the decision to load the page first, then use Axios to get the list of submissions, but I decided aginst that for now.

As such, I had my view setup along these lines:

from django.shortcuts import render
import json
from myapp.models import MyModel

def my_view(request):
    my_models = myModel.objects.all()
    model_list = []
    for model in my_models:
        new_model = {
            'id': model.id,
            'name': model.name,
            'picture': model.picture
        }
        model_list.append(new_model)

    context={
        'models': json.dumps(model_list)
    }

    return render(request, 'my_template.html')

(I would like to use model_to_dict from django.forms.models here but UUIDs don’t work nicely in my scenario…)

My Vue JS:

var models= new Vue(
    {
        el: '#models',
        delimiters: ["[%", "%]"],
        data: {
            models: model_list
        }
    }
);

End of course, the template:

{% extends 'base.html' %}
{% load static %}
{% block content %}
<div id="models" class="content">
<template v-if="models">
    <h2>Models</h2>
    <table class="table table-hover">
        <thead>
        <tr>
            <th>Photo</th>
            <th>Name</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="model in models">
            <td scope="row"><img :src="model.picture"></td>
            <td><a :href="model.id">[% model.name %]</a></td>
        </tr>
        </tbody>
    </table>
</template>
</div>
<script>
var models = {{ models }};
</script>
    <script src="{% static 'js/model_list.js' %}"></script>
{% endblock %}

The problem here was though, Django was escaping the JSON string automatically. After doing some googling I found many solutions that said to use the escapejs flag in conjunction with JSON.parse() but I wasn’t satisfied with that.

Django has a tag for disabling the auto-escaping it does though. This allows you to do the following:

<script>
    {% autoescape off %}
var model_list = {{ models }};
    {% endautoescape %}
</script>

And voila! Django renders the JSON String in such a way that Javascript can work with it right away, without having to use JSON.parse on it.

Leave a Reply

Your email address will not be published. Required fields are marked *