nb 请参阅底部的 2018 年更新
我建议不要在你的 Django 模板中放置太多 JavaScript - 它往往难以编写和调试,尤其是当你的项目扩展时。相反,尝试将所有 JavaScript 编写在模板加载的单独脚本文件中,并在模板中仅包含一个 JSON 数据对象。这允许你做一些事情,比如通过JSLint 之类的东西运行你的整个 JavaScript 应用程序,缩小它等等。你可以用一个静态的 HTML 文件来测试它,而不依赖于你的 Django 应用程序。使用像 simplejson 这样的库还可以节省您编写繁琐的序列化代码的时间。
如果你不假设你正在构建一个 AJAX 应用程序,这可能只是这样完成:
在视图中:
from django.utils import simplejson
def view(request, …):
js_data = simplejson.dumps(my_dict)
…
render_template_to_response("my_template.html", {"my_data": js_data, …})
在模板中:
<script type="text/javascript">
data_from_django = {{ my_data }};
widget.init(data_from_django);
</script>
请注意,数据类型很重要:如果my_data
是简单数字或来自不包含 HTML 的受控源的字符串,例如格式化日期,则不需要特殊处理。如果可能有用户提供的不受信任的数据,您将需要使用诸如escape或escapejs过滤器之类的东西来清理它,并确保您的 JavaScript 安全地处理数据以避免跨站点脚本攻击。
就日期而言,您可能还想考虑如何传递日期。我几乎总是发现将它们作为 Unix 时间戳传递最容易:
在Django:
time_t = time.mktime(my_date.timetuple())
在 JavaScript 中,假设您已经time_t = {{ time_t }}
对上述代码片段的结果进行了类似操作:
my_date = new Date();
my_date.setTime(time_t*1000);
最后,注意 UTC - 您需要让 Python 和 Django 日期函数以 UTC 交换数据,以避免与用户本地时间发生令人尴尬的变化。
编辑:请注意,javascript 中的 setTime 以毫秒为单位,而 time.mktime 的输出以秒为单位。这就是为什么我们需要乘以 1000
2018 年更新:我仍然喜欢 JSON 来处理复杂的值,但在这十年间,HTML5 数据 API已经获得了几乎通用的浏览器支持,并且非常方便地传递简单(非列表/字典)值,特别是如果您可能想要使用 CSS规则基于这些值应用,您不关心不受支持的 Internet Explorer 版本。
<div id="my-widget" data-view-mode="tabular">…</div>
let myWidget = document.getElementById("my-widget");
console.log(myWidget.dataset.viewMode); // Prints tabular
somethingElse.addEventListener('click', evt => {
myWidget.dataset.viewMode = "list";
});
如果您想在 Django 模板中设置初始视图状态并让它在 JavaScript 更新data-
属性时自动更新,这是将数据公开给 CSS 的一种巧妙方法。我将它用于诸如隐藏进度小部件之类的事情,直到用户选择要处理的内容或根据获取结果有条件地显示/隐藏错误,甚至诸如使用 CSS 之类的显示活动记录计数之类的事情#some-element::after { content: attr(data-active-transfers); }
。