I have a list passed through the context into the html page of a Django project which I want to read inside of a .js which contains chartjs code. The problem is that .js is reading as string and not as a list/array.
views.py
def index(request):
context = {
"data": [1, 2, 3, 4, 5]}
return render(request, 'index.html', context)
Then, in the html page I have to pass the {{ data|safe }} to a javascript like so:
<script src='{% static "js/chart.js/linechart.js" %}'
var label = "fakelabel";
var index = {{ data|safe }};
></script>
Inside the .js I'm reading the 'index' input as:
document.currentScript.getAttribute("index")
How can I fix this? ('label' is read correctly as str indeed).
{{ data|safe }} is not a safe way to output a Python object as JavaScript.
Use json_script if you want to be safe
This is how to do it.
Write your object as json:
data = {'numbers':['1', '2', '3', '4', '5']}
def index(request):
context = {"data": data}
return render(request, 'index.html', context)
<script>
var index = {{ data|json_script:'mydata' }};
<script>
Then you can use the index variable into another scrip like this:
<script>
const data = JSON.parse(document.getElementById('mydata').textContent);
mydata = data['numbers'];
</script>
You could (and probably should) point to an external JavaScript file rather than using embedded JavaScript. read here for more details
The correct way to fix the above problem is:
views.py
Inside Django views you need to pass each list inside the 'context' dict into json.dumps:
def index(request):
context ={"data": json.dumps([1, 2, 3, 4, 5])}
return render(request, 'index.html', context)
charts.html
Then, in the html script you should add {{ data|json_script:"index" }} like you you do with the 'static' tag. Then, always in your .html script you do not need to pass the 'index' list. Therefore when you call the javascript inside your .html you just need to pass:
{{ data|json_script:"index" }}
<script src='{% static "js/chart.js/linechart.js" %}'
var label = "fakelabel";
></script>
js/chart.js/linechart.js
Finally, inside you separate javascript (in this case "js/chart.js/linechart.js"), we can fetch the list with:
JSON.parse(document.getElementById('index').textContent)
You can use ajax to fetch list or dict data from views and you need to add jQuery cdn in html file.
from django.http import JsonResponse
def indexAjax(request):
context={"data":[1,2,3,4,5]}
return JsonResponse(context,safe=False)
Inside your js file or script tag
function fun(){
$.ajax({
url:"{% url'indexAjax" %},
dataType:'json',
type:'GET',
success:function(res){
console.log(res.data)
//here you can write your chartjs
}
})}