我正在尝试将来自Django的查询集传递给带有javascript的模板。
我尝试过不同的方法来解决这个问题:
1。正常方法 - 由于命名法[& gt Object:ID& lt,& gt Object:ID& lt,...]
Django View
django_list = list(Some_Object.objects.all())
模板HTML + JS
<script type="text/javascript" >
var js_list = {{django_list}};
</script>
2。 JSON方法 - Django无法将对象列表转换为json字符串 不是JSON可序列化的
Django View
django_list = list(Some_Object.objects.all())
json_list = simplejson.dumps(django_list)
模板HTML + JS
<script type="text/javascript" >
var js_list = {{json_list}};
</script>
所以,我需要一些帮助:)
任何人都有任何建议/解决方案吗?
谢谢!
答案 0 :(得分:29)
通过vashishtha-jogi回答:
更好的方法是使用DjangoJSONEncoder。它支持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)
非常容易使用。没有跳过箍转换个人 要浮动的字段。
更新:更改了使用内置json而不是simplejson的答案。
这是我的谷歌搜索经常出现的答案,并且有很多观点,更新它并保存其他人免于挖掘SO似乎是一个好主意。假设Django 1.5
。
答案 1 :(得分:24)
好的,我找到了解决方案!
主要是因为没有引用结果。当Javascript尝试解析对象时,这不会被识别为字符串。
所以,第一步是:
var js_list = {{django_list}};
更改为:
var js_list = "{{django_list}}";
在此之后,我意识到Django正在逃避角色,所以我不得不像这样替换它们:
var myJSONList = (("{{json_list}}").replace(/&(l|g|quo)t;/g, function(a,b){
return {
l : '<',
g : '>',
quo : '"'
}[b];
}));
myData = JSON.parse( myJSONList );
注意:我试图避免使用此从Django中转义字符:
var js_list = "{{json_list|safe}}";
但这不起作用,因为它与引号混淆。
最后,我找到了一种方法来避免在将其发送到Javascript之前转换为JSON的后端逻辑:
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 );
我确信这可以改进,我告诉你;)
感谢您的回答
希望对别人有帮助!
答案 2 :(得分:7)
Django querysets are serializable by JSON。某些字段类型(例如日期,显然),无法序列化。日期对象的变通方法发布在another question on JSON and Python。
我建议直接在JavaScript中创建字典。给出这样的模型:
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)
我会在模板中做这样的事情:
<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>
如果你的措辞有点糟糕且不计划在<script>
代码中插入代码,并且出于某种原因实际需要 JSON,我只是在视图中做一个循环并创建一个dict
的列表,JSON没有序列化的问题,而且JavaScript没有理解的问题。
答案 3 :(得分:7)
编辑:请不要使用此方法,请参阅@ agconti的回答。
使用escapejs过滤器:https://docs.djangoproject.com/en/1.4/ref/templates/builtins/#escapejs
转储列表的示例:
var foo = [{% for x in y %}'{{ x|escapejs }}',{% endfor %}]
答案 4 :(得分:6)
您可以在Django中使用safe和escapejs内置过滤器的组合。
var json_string = unescape({{json_list | safe | escapejs}});
var json_data = JSON.parse(json_string);
答案 5 :(得分:4)
您的问题是,通常情况下,您的要求不明确。你想要JSON看起来到底是什么样的?你说你想“序列化查询集”,但格式是什么?您想要每个模型实例,选择中的所有字段,还是只需要unicode表示?当你回答这个问题时,你就会知道如何解决问题。
例如,一种方法可能是使用values
queryset方法为每个实例输出字段字典,并将其序列化(您需要先将其转换为列表):
data = SomeObject.objects.values('field1', 'field2', 'field3')
serialized_data = simplejson.dumps(list(data))
答案 6 :(得分:3)
您必须将字符串标记为安全,以确保它不会被转义。
在我的一个项目中我使用它:
# 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))
并在模板中
{% load jsonify %}
<script type="text/javascript" >
var js_list = {{ python_list|jsonify|escapejs }};
</script>
但您可能更愿意在模板中添加mark_safe或use | safe以避免所有>
内容
如果问题是处理复杂的python对象,你可能需要这样处理你的处理程序:JSON datetime between Python and JavaScript
答案 7 :(得分:2)
Django为您在此尝试的场景提供内置帮助。它是这样的:
你的视图中有一个python序列,列表,字典等,我们称之为py_object
。一种方法是在将其传递给渲染引擎之前对其进行jsonify。
from django.shortcuts import render_to_response
import json
然后再使用这样......
render_to_response('mypage.html',{'js_object':json.dumps(py_object)})
在你的模板中,然后使用safe
过滤器将已经jsonized的对象从python导入javascript,就像这样......
data = {{ js_object|safe }}
这应该可以解决你的问题。
答案 8 :(得分:1)
自Django 2.1以来,就有json-script template tag。从文档中:
json_script
安全地将Python对象作为JSON输出,包装在标记中, 准备与JavaScript一起使用。
参数:标记的HTML“ id”。
例如:
{{ value|json_script:"hello-data" }}
如果value是字典
{'hello': 'world'}
,则输出为:<script id="hello-data" type="application/json"> {"hello": "world"} </script>
结果数据可以用JavaScript访问 像这样:
var value = JSON.parse(document.getElementById('hello-data').textContent);
通过转义字符“ <”,“>”和“&”来缓解XSS攻击。对于 例如,如果值为
{'hello': 'world</script>&'}
,则输出为:<script id="hello-data" type="application/json"> {"hello": "world\\u003C/script\\u003E\\u0026amp;"} </script>
这是兼容的 具有严格的内容安全策略,该策略禁止页内脚本 执行。它还保持了被动数据之间的清晰隔离 和可执行代码。
答案 9 :(得分:0)
综合答案(我的环境:Django 2.0)
在views.py
中import json
data= []
// fil the list
context['mydata'] = json.dumps({'data':data})
在模板中
<script type="text/javascript">
var mydataString = "{{mydata|escapejs}}";
console.log(JSON.parse(mydataString));
</script>
答案 10 :(得分:0)
对我来说,发送整个QuerySet(同时保留字段名称;发送object
而不是list
)。我使用了以下
# views.py
units = Unit.objects.all()
units_serialized = serializers.serialize('json', units)
context['units'] = units_serialized
,只需在模板中使用safe
标记
# template.html
<script>
console.log({{units|safe}});
</script>
答案 11 :(得分:0)
注意django 2.1
在django文档上,我发现这有点令人困惑,因此只是简单地解释了一些简单的方法。
我们通常会像
这样使用{{ my_info }}
或根据我们的需要遍历它。但是,如果我们使用以下过滤器,
json_script
我们可以安全地将此值输出为JSON
{{ my_info|json_script:"my-info" }}
我们的数据已添加为JSON,并包装在脚本标签中,我们可以看到数据。现在,我们可以像下面这样在JavaScript中查找该值:
info = JSON.parse(document.getElementById('my-info').textContent);
答案 12 :(得分:0)
要么;
使用{{ django_list }}
读取对象,然后删除不需要的字符
或做;
{{ django_list | safe}}
答案 13 :(得分:0)
还要注意确保从Django正确输出JSON数据,否则前端的所有试验都将浪费时间。在我的情况下,我不能将JsonResponse用作render函数的一部分,所以我做了以下事情:
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
})
在前端:
{% 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 %}