Django模板变量和Javascript
-
08-07-2019 - |
题
当我使用Django模板渲染器渲染页面时,我可以传入包含各种值的字典变量,以使用{{ myVar }}
在页面中操作它们。
有没有办法在Javascript中访问相同的变量(也许使用DOM,我不知道Django如何使变量可访问)?我希望能够使用基于传入的变量中包含的值的AJAX查找来查找详细信息。
解决方案
{{variable}}
直接替换为HTML。做一个观察源;它不是<!>“变量<!>”;或类似的东西。它只是渲染文本。
话虽如此,您可以将这种替换放入JavaScript中。
<script type="text/javascript">
var a = "{{someDjangoVariable}}";
</script>
这会给你<!>“动态<!>”;的JavaScript。
其他提示
注意检查票据#17419 ,了解有关添加类似标签的讨论通过使用此模板标记和用户生成的数据引入Django核心和可能的XSS漏洞。来自amacneil的评论讨论了故障单中提出的大部分问题。
我认为最灵活,最方便的方法是为要在JS代码中使用的变量定义模板过滤器。这样可以确保您的数据被正确转义,并且可以将其用于复杂的数据结构,例如dict
和list
。这就是为什么我写这个答案,尽管有很多赞成的答案已被接受。
以下是模板过滤器的示例:
// 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>
对我有用的解决方案是使用模板中的隐藏输入字段
<input type="hidden" id="myVar" name="variable" value="{{ variable }}">
然后以这种方式获取javascript中的值,
var myVar = document.getElementById("myVar").value;
当Django返回变量时,它会将所有引号变为"
。使用{{someDjangoVariable|safe}}
会导致Javascript错误。
要解决此问题,请使用Javascript .replace
:
<script type="text/javascript">
var json = "{{someDjangoVariable}}".replace(/"/g,"\"")
</script>
对于字典,您最好先编码为JSON。您可以使用simplejson.dumps(),或者如果要从App Engine中的数据模型进行转换,可以使用GQLEncoder库中的encode()。
从Django 2.1开始,专门为此用例引入了一个新的内置模板标记:json_script
。
https://docs.djangoproject.com/en /2.1/ref/templates/builtins/#json-script 。
新标记将安全地序列化模板值并防止XSS。
以下是我正在做的事情: 我为我的模板修改了我的base.html文件并将其放在底部:
{% if DJdata %}
<script type="text/javascript">
(function () {window.DJdata = {{DJdata|safe}};})();
</script>
{% endif %}
然后当我想在javascript文件中使用变量时,我创建了一个DJdata字典,并通过json将其添加到上下文中:context['DJdata'] = json.dumps(DJdata)
希望它有所帮助!
我正面临着simillar问题,而S.Lott建议的答案为我工作。
<script type="text/javascript">
var a = "{{someDjangoVariable}}"
</script>
但是我想在此指出主要实施限制。 如果您计划将javascript代码放在不同的文件中,并将该文件包含在模板中。这不起作用。
仅当主模板和javascript代码位于同一文件中时才有效。 可能django团队可以解决这个限制。
我也一直在努力解决这个问题。从表面上看,上述解决方案似乎应该有效。但是,django体系结构要求每个html文件都有自己的呈现变量(即{{contact}}
呈现为contact.html
,而{{posts}}
呈现为例如index.html
等等)。另一方面,<script>
标签出现在{%endblock%}
base.html
之后<script src="static/js/somecode.js"></script>
和<=>继承。这基本上意味着包括
<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;
并像往常一样在<=>中加入<=>。 当然,这仅仅是获取内容。关于安全性,请按照其他答案。
对于存储在Django字段中的JavaScript对象作为文本,需要再次成为动态插入页面脚本的JavaScript对象,您需要同时使用escapejs
和JSON.parse()
:
var CropOpts = JSON.parse("{{ profile.last_crop_coords|escapejs }}");
Django的<=>正确处理引用,<=>将字符串转换回JS对象。
注意,如果要将变量传递给外部.js脚本,则需要在脚本标记之前添加另一个声明全局变量的脚本标记。
<script type="text/javascript">
var myVar = "{{ myVar }}"
</script>
<script type="text/javascript" src="{% static "scripts/my_script.js" %}"></script>
data
在视图中通常在get_context_data
def get_context_data(self, *args, **kwargs):
context['myVar'] = True
return context