che*_*vik 53 javascript python django
我正在使用Django和Apache来提供网页服务.我的JavaScript代码目前包含一个数据对象,其值根据用户从选项菜单中的选择显示在各种HTML小部件中.我想从Python字典中获取这些数据.我想我知道如何在JavaScript中嵌入JavaScript代码,但是如何在该脚本中嵌入数据对象(动态),以便脚本的功能可以使用它?
换句话说,我想从Python字典创建一个JavaScript对象或数组,然后将该对象插入到JavaScript代码中,然后将该JavaScript代码插入到HTML中.
我认为这种结构(例如,嵌入在JavaScript代码中的变量中的数据)不是最理想的,但作为一个新手,我不知道其他选择.我已经看过Django序列化函数的编写,但这些对我没有帮助,直到我可以将数据放到我的JavaScript代码中.
我还没有使用像jQuery这样的JavaScript库.
Chr*_*ams 78
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, …})
Run Code Online (Sandbox Code Playgroud)
在模板中:
<script type="text/javascript">
data_from_django = {{ my_data }};
widget.init(data_from_django);
</script>
Run Code Online (Sandbox Code Playgroud)
请注意,数据类型很重要:如果my_data是一个简单的数字或来自受控源的不包含HTML的字符串,例如格式化的日期,则不需要特殊处理.如果用户可能提供不受信任的数据,则需要使用escape或escapejs过滤器对其进行清理,并确保JavaScript安全地处理数据以避免跨站点脚本攻击.
就日期而言,您可能还想考虑如何传递日期.我几乎总是发现将它们作为Unix时间戳传递最简单:
在Django:
time_t = time.mktime(my_date.timetuple())
Run Code Online (Sandbox Code Playgroud)
在JavaScript中,假设您已完成time_t = {{ time_t }}上述代码段的结果:
my_date = new Date();
my_date.setTime(time_t*1000);
Run Code Online (Sandbox Code Playgroud)
最后,请注意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";
});
Run Code Online (Sandbox Code Playgroud)
如果要在Django模板中设置初始视图状态并在JavaScript更新data-属性时自动更新,这是向CSS公开数据的一种巧妙方法.我将此用于隐藏进度窗口小部件,直到用户选择要处理的内容或根据获取结果有条件地显示/隐藏错误,甚至使用CSS等显示活动记录计数#some-element::after { content: attr(data-active-transfers); }.
wil*_*ack 39
对于可能遇到此问题的任何人,请确保在模板中以安全模式呈现json对象.您可以像这样手动设置
<script type="text/javascript">
data_from_django = {{ my_data|safe }};
widget.init(data_from_django);
</script>
Run Code Online (Sandbox Code Playgroud)
截至 2018 年年中,最简单的方法是使用 Python 的 JSON 模块,现在已弃用 simplejson。请注意,正如@wilblack 提到的,您需要使用带有选项的safe过滤器或autoescape标记来防止 Django 的自动转义off。在视图中的两种情况下,您都将字典的内容添加到上下文中
视图集.py
import json
def get_context_data(self, **kwargs):
context['my_dictionary'] = json.dumps(self.object.mydict)
Run Code Online (Sandbox Code Playgroud)
然后在模板中添加@wilblack 建议:
模板.html
<script>
my_data = {{ my_dictionary|safe }};
</script>
Run Code Online (Sandbox Code Playgroud)