通过 Django 将 Python 数据传递给 JavaScript [英] Passing Python Data to JavaScript via Django

查看:52
本文介绍了通过 Django 将 Python 数据传递给 JavaScript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Django 和 Apache 来提供网页.我的 JavaScript 代码当前包含一个数据对象,该对象的值将根据用户从选项菜单中的选择显示在各种 HTML 小部件中.我想从 Python 字典中导出这些数据.我想我知道如何将 JavaScript 代码嵌入到 HTML 中,但是如何将数据对象嵌入到该脚本中(动态)以便脚本的函数可以使用它?

I'm using Django and Apache to serve webpages. My JavaScript code currently includes a data object with values to be displayed in various HTML widgets based on the user's selection from a menu of choices. I want to derive these data from a Python dictionary. I think I know how to embed the JavaScript code in the HTML, but how do I embed the data object in that script (on the fly) so the script's functions can use it?

换句话说,我想从 Python 字典中创建一个 JavaScript 对象或数组,然后将该对象插入到 JavaScript 代码中,然后将该 JavaScript 代码插入到 HTML 中.

Put another way, I want to create a JavaScript object or array from a Python dictionary, then insert that object into the JavaScript code, and then insert that JavaScript code into the HTML.

我认为这种结构(例如,嵌入在 JavaScript 代码中的变量中的数据)是次优的,但作为新手,我不知道替代方案.我看过有关 Django 序列化函数的文章,但在我首先将数据导入 JavaScript 代码之前,这些对我没有帮助.

I suppose this structure (e.g., data embedded in variables in the JavaScript code) is suboptimal, but as a newbie I don't know the alternatives. I've seen write-ups of Django serialization functions, but these don't help me until I can get the data into my JavaScript code in the first place.

我(还)没有使用像 jQuery 这样的 JavaScript 库.

I'm not (yet) using a JavaScript library like jQuery.

推荐答案

n.b.见底部 2018 年更新

n.b. see 2018 update at the bottom

我建议不要在您的 Django 模板中放置太多 JavaScript - 它往往难以编写和调试,尤其是当您的项目扩展时.相反,尝试将所有 JavaScript 编写在模板加载的单独脚本文件中,并在模板中仅包含一个 JSON 数据对象.这允许你做一些事情,比如通过诸如 JSLint 之类的东西运行你的整个 JavaScript 应用程序,缩小它等等,你可以使用静态 HTML 文件对其进行测试,对您的 Django 应用程序没有任何依赖.使用像 simplejson 这样的库还可以节省您编写繁琐的序列化代码的时间.

I recommend against putting much JavaScript in your Django templates - it tends to be hard to write and debug, particularly as your project expands. Instead, try writing all of your JavaScript in a separate script file which your template loads and simply including just a JSON data object in the template. This allows you to do things like run your entire JavaScript app through something like JSLint, minify it, etc. and you can test it with a static HTML file without any dependencies on your Django app. Using a library like simplejson also saves you the time spent writing tedious serialization code.

如果您不假设您正在构建 AJAX 应用程序,则可以这样做:

If you aren't assuming that you're building an AJAX app this might simply be done like this:

在视图中:

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 的受控源的字符串,例如格式化的日期,则不需要特殊处理.如果可能有用户提供的不受信任的数据,您将需要使用诸如 escapeescapejs过滤并确保您的 JavaScript 安全地处理数据,以避免跨站脚本攻击.

Note that the type of data matters: if my_data is a simple number or a string from a controlled source which doesn't contain HTML, such as a formatted date, no special handling is required. If it's possible to have untrusted data provided by a user you will need to sanitize it using something like the escape or escapejs filters and ensure that your JavaScript handles the data safely to avoid cross-site scripting attacks.

就日期而言,您可能还想考虑如何传递日期.我几乎总是发现将它们作为 Unix 时间戳传递最容易:

As far as dates go, you might also want to think about how you pass dates around. I've almost always found it easiest to pass them as Unix timestamps:

在 Django 中:

In Django:

time_t = time.mktime(my_date.timetuple())

在 JavaScript 中,假设您已经使用上述代码段的结果执行了类似 time_t = {{ time_t }} 的操作:

In JavaScript, assuming you've done something like time_t = {{ time_t }} with the results of the snippet above:

my_date = new Date();
my_date.setTime(time_t*1000);

最后,注意 UTC - 您需要让 Python 和 Django 日期函数以 UTC 交换数据,以避免与用户本地时间发生令人尴尬的变化.

Finally, pay attention to UTC - you'll want to have the Python and Django date functions exchange data in UTC to avoid embarrassing shifts from the user's local time.

请注意,javascript 中的 setTime 以毫秒为单位,而 time.mktime 的输出为秒.这就是为什么我们需要乘以 1000

EDIT : Note that the setTime in javascript is in millisecond whereas the output of time.mktime is seconds. That's why we need to multiply by 1000

2018 年更新:我仍然喜欢 JSON 来处理复杂的值,但在接下来的十年中 HTML5 数据 API 已获得接近通用浏览器支持,非常方便传递简单(非列表/字典)值,特别是如果您可能希望基于这些值应用 CSS 规则并且您不关心不受支持的 Internet Explorer 版本.

2018 Update: I still like JSON for complex values but in the intervening decade the HTML5 data API has attained near universal browser support and it's very convenient for passing simple (non-list/dict) values around, especially if you might want to have CSS rules apply based on those values and you don't care about unsupported versions of 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{ 内容: attr(data-active-transfers);}.

This is a neat way to expose data to CSS if you want to set the initial view state in your Django template and have it automatically update when JavaScript updates the data- attribute. I use this for things like hiding a progress widget until the user selects something to process or to conditionally show/hide errors based on fetch outcomes or even something like displaying an active record count using CSS like #some-element::after { content: attr(data-active-transfers); }.

这篇关于通过 Django 将 Python 数据传递给 JavaScript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆