I\'m trying to pass a Query Set from Django to a template with javascript.
I\'ve tried different approaches to solve this:
1. Normal Approach - Javas
Answer by vashishtha-jogi:
A better approach is to use DjangoJSONEncoder. It has support for Decimal.
import json from django.core.serializers.json import DjangoJSONEncoder prices = Price.objects.filter(product=product).values_list('price','valid_from') prices_json = json.dumps(list(prices), cls=DjangoJSONEncoder)
Very easy to use. No jumping through hoops for converting individual fields to float.
Update : Changed the answer to use builtin json instead of simplejson.
This is answer came up so often in my google searches and has so many views, that it seems like a good idea to update it and save anyone else from digging through SO. Assumes Django 1.5
.
Ok, I found the solution!
Mostly it was because of not quoting the results. When Javascript was trying to parse the object this wasn't recognized as string.
So, first step is:
var js_list = {{django_list}};
changed to:
var js_list = "{{django_list}}";
After this I realized that Django was escaping characters so I had to replace them like this:
var myJSONList = (("{{json_list}}").replace(/&(l|g|quo)t;/g, function(a,b){
return {
l : '<',
g : '>',
quo : '"'
}[b];
}));
myData = JSON.parse( myJSONList );
Note: I tried to avoid escaping characters from Django using this:
var js_list = "{{json_list|safe}}";
But this doesn't work because it gets confused with the quotes.
Finally I found a way to avoid the logic on the backend of converting to JSON before sending it to Javascript:
var myDjangoList = (("{{django_list |safe}}").replace(/&(l|g|quo)t;/g, function(a,b){
return {
l : '<',
g : '>',
quo : '"'
}[b];
}));
myDjangoList = myDjangoList.replace(/u'/g, '\'')
myDjangoList = myDjangoList.replace(/'/g, '\"')
myData = JSON.parse( myDjangoList );
I'm sure this can be improved, I let this to you ;)
Thanks for your answers
Hope it helps to someone else!
NOTE for django 2.1
i found this a little confusing on django documentation so simply explaining a little bit easy way.
we would normally use this like
{{ my_info }}
or loop over it depending on what we needed. But if we use the following filter,
json_script
we can safely output this value as JSON
{{ my_info|json_script:"my-info" }}
Our data has been added as JSON, wrapped in a script tag, and we can see the data. We can now use this value by looking it up in JavaScript like so:
info = JSON.parse(document.getElementById('my-info').textContent);
either;
read object using {{ django_list }}
and then remove unwanted characters
or do;
{{ django_list | safe}}
Be careful on also making sure that you output JSON data correctly from Django, otherwise all trials on the frontend side will be a waste of time. In my case I could not use JsonResponse as part of the render function so I did the following:
def view(self, request):
data = []
machine_data = list(Machine.objects.filter(location__isnull=False).values_list('serial', 'location', 'customer__name'))
data.append({
"locations": machine_data,
})
return render(request, 'admin/company/device/map.html', {
"machines": data
})
And on the frontend:
{% block content %}
{{ machines_with_location|json_script:"machineLocationData" }}
<div id="content-main">
<h1>Title</h1>
<script type="text/javascript">
const locationDataFromJson = JSON.parse(document.getElementById('machineLocationData').textContent);
</script>
</div>
{% endblock %}
Consolidated answer (my env: Django 2.0)
In views.py
import json
data= []
// fil the list
context['mydata'] = json.dumps({'data':data})
In template
<script type="text/javascript">
var mydataString = "{{mydata|escapejs}}";
console.log(JSON.parse(mydataString));
</script>