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
Your problem is that, as so often, your requirements are under-specified. What exactly do you want the JSON to look like? You say you want to "serialize the queryset", but in what format? Do you want all the fields from each model instance, a selection, or just the unicode representation? When you've answered that question, you'll know how to solve your problem.
One approach, for example, might be to use the values
queryset method to output a dictionary of fields for each instance, and serialize that (you need to convert it to a list first):
data = SomeObject.objects.values('field1', 'field2', 'field3')
serialized_data = simplejson.dumps(list(data))
You can use the combination of safe and escapejs built-in filter in Django.
var json_string = unescape({{json_list | safe | escapejs}});
var json_data = JSON.parse(json_string);
For me to send the whole QuerySet (while preserving the fields names; sending object
not list
). I used the following
# views.py
units = Unit.objects.all()
units_serialized = serializers.serialize('json', units)
context['units'] = units_serialized
and just use safe
tag in the template
# template.html
<script>
console.log({{units|safe}});
</script>
Django querysets are serializable by JSON. Some field types (such as date, apparently), can't be serialized at is. A workaround for date objects is posted in another question on JSON and Python.
I would recommend creating dictionaries directly in the JavaScript itself. Given models like this:
class Article(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField()
content = models.TextField()
class Author(models.Model):
article = models.ForeignKey("Article", related_name="authors")
first_name=models.CharField(max_length=100)
last_name=models.CharField(max_length=100)
I'd do something like this in the template:
<script type="text/javascript">
var articles = [
{% for article in article_list %}
{% if not forloop.first %},{% endif %}
{
title: "{{ article.title }}",
slug: "{{ article.slug }}",
content: "{{ article.content }}",
authors: [
{% for author in article.authors.all %}
{% if not forloop.first %},{% endif %}
{
first_name: "{{ author.first_name }}",
last_name: "{{ author.last_name }}",
}
{% endfor %}
]
}
{% endfor %}
]
</script>
If you maybe worded the question a little poorly and aren't planning on inserting code in a <script>
tag and actually need JSON for some reason, I'd simply do a loop in the view and create a list of dict
s, which JSON has no problem serializing, and JavaScript no problem in understanding.
You have to mark the string as safe to be sure it's not escaped.
in one of my project I use it like this:
# app/templatetag/jsonify.py
from django import template
from django.utils.safestring import mark_safe
import json
register = template.Library()
@register.filter
def jsonify(list):
return mark_safe(json.dumps(list))
and in the template
{% load jsonify %}
<script type="text/javascript" >
var js_list = {{ python_list|jsonify|escapejs }};
</script>
but you may prefer to just add mark_safe or use |safe in the template to avoid all >
stuff
If the problem is for handling complex python object you may have to do your handler like this: JSON datetime between Python and JavaScript
Django offers in-built help for the very scenario you are trying to do here. It goes something like this:
You have a python sequence, list, dictionary, etc in your view, let's call it py_object
. One approach is to jsonify it before passing it to the rendering engine.
from django.shortcuts import render_to_response
import json
Then later on use like this...
render_to_response('mypage.html',{'js_object':json.dumps(py_object)})
In you template, then use the safe
filter to import the already jsonized object from python into javascript, like this...
data = {{ js_object|safe }}
That should solve your problem i hope.