I am working on a Django / Python website. I have a page where I want to display a table of search results. The list of results is passed in to the template as normal.
I also want to make this list of objects accessible to the JavaScript code.
My first solution was just create another view that returned JSON format. But each page load required calling the query twice. So then I tried only downloading the data using the JSON view and printing the table using JavaScript.
But this is also not desirable as now the presentation layer is mixed into the JavaScript code.
Is there a way to create a JavaScript object from the Python list as the page is rendered?
Solution
I created a custom template filter, see custom template tags and filters.
from django.core.serializers import serialize
from django.db.models.query import QuerySet
from django.utils import simplejson
from django.utils.safestring import mark_safe
from django.template import Library
register = Library()
def jsonify(object):
if isinstance(object, QuerySet):
return mark_safe(serialize('json', object))
return mark_safe(simplejson.dumps(object))
register.filter('jsonify', jsonify)
jsonify.is_safe = True
The calls to mark_safe are important. Otherwise Django will escape it.
In the template:
//Without template filter (you'll need to serialise in the view)
var data = jQuery.parseJSON('{{ json_data|safe }}');
alert(data.length);
//Using the template filter
var data2 = jQuery.parseJSON('{{ record_list|jsonify }}');
alert(data2.length);
Note the single quotes around the template tag.
Although my next question would be - is it REALLY safe?
An updated version working in django 1.8 of the above template tag that also handles being passed a flat values list, ie. values_list('myfield', flat=True):
from django.core.serializers import serialize
from django.db.models.query import QuerySet, ValuesListQuerySet
from django.template import Library
import json
register = Library()
@register.filter( is_safe=True )
def jsonify(object):
if isinstance(object, ValuesListQuerySet):
return json.dumps(list(object))
if isinstance(object, QuerySet):
return serialize('json', object)
return json.dumps(object)
How about a filter that dumps a Python value to JSON? Here's a sample implementation:
http://djangosnippets.org/snippets/201/
Since a JSON value also happens to be a valid right-hand side for a Javascript assignment, you can simply put something like...
var results = {{results|jsonify}};
inside your script.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With