Django模板变量和Javascript

当我使用Django模板渲染器渲染一个页面时,我可以传入一个包含各种值的字典变量,使用{{ myVar }}在页面中操作它们。

是否有一种方法可以在Javascript中访问相同的变量(可能使用DOM,我不知道Django如何使变量可访问)?我希望能够根据传入的变量中包含的值使用AJAX查找详细信息。

334044 次浏览

\{\{variable}}直接被替换到HTML中。做一个查看源码;它不是一个“变量”或类似的东西。它只是渲染文本。

话虽如此,您可以在JavaScript中加入这种替换。

<script type="text/javascript">
var a = "\{\{someDjangoVariable}}";
</script>

这为您提供了“动态”javascript。

对于字典,最好先编码成JSON。你可以使用simplejson.dumps(),或者如果你想从App Engine中的数据模型转换,你可以使用GQLEncoder库中的encode()。

一个对我有用的解决方案是在模板中使用隐藏的输入字段

<input type="hidden" id="myVar" name="variable" value="\{\{ variable }}">

然后以这种方式获取javascript的值,

var myVar = document.getElementById("myVar").value;

谨慎检查票据# 17419讨论在Django核心中添加类似的标签,以及使用此模板标签与用户生成的数据可能引入的XSS漏洞。来自amacneil的评论讨论了票中提出的大部分问题。


我认为最灵活和方便的方法是为你想在JS代码中使用的变量定义一个模板过滤器。这允许你确保你的数据被正确转义,并且你可以将它用于复杂的数据结构,如dictlist。这就是为什么我写这个答案,尽管有一个公认的答案,有很多赞。

下面是一个模板过滤器的例子:

// myapp/templatetags/js.py


from django.utils.safestring import mark_safe
from django.template import Library


import json




register = Library()




@register.filter(is_safe=True)
def js(obj):
return mark_safe(json.dumps(obj))

这个模板过滤器将变量转换为JSON字符串。你可以这样使用它:

// myapp/templates/example.html


{% load js %}


<script type="text/javascript">
var someVar = \{\{ some_var | js }};
</script>
下面是我做的非常简单的事情: 我修改了模板的base.html文件,并把它放在底部:

{% if DJdata %}
<script type="text/javascript">
(function () {window.DJdata = \{\{DJdata|safe}};})();
</script>
{% endif %}

然后当我想在javascript文件中使用一个变量时,我创建了一个DJdata字典,并通过json: context['DJdata'] = json.dumps(DJdata)将它添加到上下文

希望能有所帮助!

我也遇到过类似的问题,S.Lott提出的答案对我很有用。

<script type="text/javascript">
var a = "\{\{someDjangoVariable}}"
</script>
然而,我想在这里指出主要实施限制。 如果你打算把javascript代码放在不同的文件中,并将该文件包含在你的模板中。这是行不通的 只有当你的主模板和javascript代码在同一个文件中时,这个才会起作用。 也许django团队可以解决这个限制

对于作为文本存储在Django字段中的JavaScript对象,它需要再次成为动态插入到页面脚本中的JavaScript对象,你需要使用escapejsJSON.parse():

var CropOpts = JSON.parse("\{\{ profile.last_crop_coords|escapejs }}");

Django的escapejs可以正确地处理引号,而JSON.parse()则将字符串转换回JS对象。

注意,如果你想将一个变量传递给外部的.js脚本,那么你需要在你的script标记之前加上另一个声明全局变量的script标记。

<script type="text/javascript">
var myVar = "\{\{ myVar }}"
</script>


<script type="text/javascript" src="{% static "scripts/my_script.js" %}"></script>

data在视图中定义,通常在get_context_data . c中定义

def get_context_data(self, *args, **kwargs):
context['myVar'] = True
return context

我也一直在挣扎。表面上看,上述解决方案似乎是可行的。然而,django架构要求每个html文件都有自己的呈现变量(也就是说,\{\{contact}}呈现为contact.html,而\{\{posts}}呈现为例如index.html等等)。另一方面,<script>标记出现在base.html中的{%endblock%}之后,而contact.htmlindex.html继承自base.html。这基本上意味着任何解包括

<script type="text/javascript">
var myVar = "\{\{ myVar }}"
</script>

必然会失败,因为变量和脚本不能共存于同一个文件中。

我最终想出了一个简单的解决方案,对我来说,就是简单地用一个带有id的标签包装变量,然后在js文件中引用它,就像这样:

// index.html
<div id="myvar">\{\{ myVar }}</div>

然后:

// somecode.js
var someVar = document.getElementById("myvar").innerHTML;

并且像往常一样在base.html中包含<script src="static/js/somecode.js"></script>。 当然这只是关于得到的内容。关于安全问题,请参考其他答案。< / p >

从Django 2.1开始,专门为这个用例引入了一个新的内置模板标记:json_script

https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#json-script

新标记将安全地序列化模板值并防止XSS。

Django文档摘录:

安全输出Python对象为JSON,包装在标签中,

. JavaScript

您可以组装整个脚本,其中数组变量是在字符串中声明的,如下所示:

views.py

    aaa = [41, 56, 25, 48, 72, 34, 12]
prueba = "<script>var data2 =["
for a in aaa:
aa = str(a)
prueba = prueba + "'" + aa + "',"
prueba = prueba + "];</script>"

这将生成如下所示的字符串

prueba = "<script>var data2 =['41','56','25','48','72','34','12'];</script>"

获得该字符串后,必须将其发送到模板

views.py

return render(request, 'example.html', {"prueba": prueba})

在模板中,您接收到它,并以一种文学的方式将其解释为HTM代码,例如,就在需要它的javascript代码之前

模板

\{\{ prueba|safe  }}

下面是代码的其余部分,请记住在示例中使用的变量是data2

<script>
console.log(data2);
</script>

这样就可以保持数据的类型,在本例中是一种安排

Javascript中有两件事对我有用:

'\{\{context_variable|escapejs }}'
< p >及其他: 在views.py

from json import dumps as jdumps


def func(request):
context={'message': jdumps('hello there')}
return render(request,'index.html',context)

在html中:

\{\{ message|safe }}

我在Django 2.1中使用这种方法,对我来说是安全的(参考):

Django的一面:

def age(request):
mydata = {'age':12}
return render(request, 'test.html', context={"mydata_json": json.dumps(mydata)})

Html:

<script type='text/javascript'>
const  mydata = \{\{ mydata_json|safe }};
console.log(mydata)
</script>

我发现我们可以这样传递Django变量到javascript函数:-

<button type="button" onclick="myJavascriptFunction('\{\{ my_django_variable }}')"></button>
<script>
myJavascriptFunction(djangoVariable){
alert(djangoVariable);
}
</script>

Django 2.1+使用内置模板标记json_script实现了一个很好的简单方法。一个简单的例子是:

在模板中声明你的变量:

\{\{ variable|json_script:'name' }}

然后在<script> Javascript中调用该变量:

var js_variable = JSON.parse(document.getElementById('name').textContent);

对于更复杂的变量,如“User”,你可能会得到类似“User类型的对象不是JSON serializable”这样的错误。使用Django内置的序列化器。在这种情况下,您可以使用Django Rest框架来支持更复杂的变量。

new 文档表示使用\{\{ mydata|json_script:"mydata" }}来防止代码注入。

一个很好的例子是在这里:

\{\{ mydata|json_script:"mydata" }}
<script>
const mydata = JSON.parse(document.getElementById('mydata').textContent);
</script>

有不同的答案指向json_script。与人们可能认为的相反,这并不是一个万能的解决方案。

例如,当我们想要将For循环中生成的动态变量传递给JavaScript时,最好使用数据属性之类的东西。

点击这里查看更多细节