在单击事件中调用Django URL的JavaScript方法

13

我有一个位于模板内的JavaScript onclick事件,我想通过它调用我的Django URL并带上ID参数,像这样:

$(document).on('click', '.alink', function () {
        var id = $(this).attr('id');
        document.location.href ="{% url 'myapp:productdetailorder' id %}"
});

这个方案完全行不通。有什么建议吗?

提前感谢!!


你的目标是什么?Django模板标签中引用的变量id与javascript中的不同。在javascript中使用Django模板通常会导致代码不够优雅,但听起来你想要做的实质上是在javascript中执行字符串连接。将Django标签视为返回字符串的函数,并编写相应的javascript进行连接。 - fvgs
嗨,感谢您的评论。如果是产品ID,我想将其设置为URL,以便我的视图可以处理它并在另一个模板中显示其信息。我知道我可能做错了,但这正是我需要的:一种很好的方法来实现它。 - jsanchezs
看起来相关的URL是指向您的API中的一个端点。由于API不是动态的,应该保持稳定,除非您对其进行更改,因此通常会在JavaScript代码中硬编码此URL。因此,我建议您在JavaScript代码中将URL写出来。 - fvgs
5个回答

31

我认为最好的方法是创建一个带有 URL 的模板 data-* 属性,然后使用 JavaScript 检索它。这样,您可以避免将 js/django 模板内容混在一起。此外,我将所有 JS 文件都保留在视图之外的单独文件中(这通常是一个更好的做法),因此尝试混合这两个东西是行不通的。

例如,如果您想要一个 URL,只需创建一个隐藏的 HTML 元素:

<input type="hidden" id="Url" data-url="{% url 'myapp:productdetail' id %}" />

然后,在你的 JS 中:

$(document).on('click', '.alink', function () {
    var url = $("#Url").attr("data-url");
});      

我经常使用这个模式来创建下拉列表,这样我就不必在首次渲染页面时提供所有选项(通常会加快页面速度)。


1
使用 {% url %} 或任何其他可能添加用户数据的标签都容易受到 XSS 攻击 - 在模板中将数据传递给 JavaScript 的安全方式是使用 json_script 过滤器:https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#json-script - Adam Johnson

22
您正在尝试访问用户在前端创建的JavaScript变量,并将其用于 Django 模板中的后端。但是,您已经知道这不起作用。
更好的选择是在 JavaScript 中重构 URL:
$(document).on('click', '.alink', function () {
    // Generate URL without "id" bit
    var url = "{% url 'myapp:productdetail' %}";

    var id = $(this).attr('id');

    // Construct the full URL with "id"
    document.location.href = url + "/" + id;
});

如果您没有一个Django URL帮助程序可以返回所需的URL,您可以打印出任何一个URL,然后在JavaScript中进行替换,如下所示:

如果您没有Django URL帮助程序返回所需的URL,您可以打印出任何一个URL,然后在JavaScript中进行替换,如下所示:

$(document).on('click', '.alink', function () {
    var url = "{% url 'myapp:productdetail' 123 %}";
    var id = $(this).attr('id');

    // Construct the full URL with "id"
    document.location.href = url.replace('123', id);
});

谢谢你的回答,我知道我们很接近了,但是用这种方式做会抛出一个反向URL错误:找不到参数为“()”和关键字参数为“{}”的“productdetail”的反向。尝试了1个模式:“['myapp/product/(?P<id_ac>\d+)/$']”.....我认为这是因为ID参数从一开始就是必需的,你觉得呢? - jsanchezs
是的,那是Django的路由助手。只需调用另一个URL助手即可打印所需的值。如果您没有,请使用任何ID进行打印并在JS中替换它。我会更新我的答案。 - Uzbekjon
1
使用 {% url %} 或任何其他可能添加用户数据的标签都容易受到 XSS 攻击 - 在模板中将数据传递给 JavaScript 的安全方式是使用 json_script 过滤器:https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#json-script - Adam Johnson
@AdamJohnson 我看了链接,但由于我的知识不足和无知,无法理解如何以更安全的方式实现上述目标。所以你能写出代码来展示如何做吗?而且所有这些都必须在<script></script>内完成。值不能在模板中分配,而是在JS中。谢谢 - Sardar Faisal
这种方法不是一个好主意。如果这个 JavaScript 没有经过 Django 模板引擎(即你把它放在静态文件中,它应该在那里),会发生什么?你的 URL 不会被渲染出来。 - Ben

6
问题似乎在于你在js静态文件中使用了django模板语言(我说的对吗?) 尝试将该变量移动到html模板文件中,例如:
<script type=text/javascript>
var a = "{% url'myapp:productdetail' id %}" </script>

在静态js文件中:

document.location.href = a;

不要混合使用JS和Html!维护起来真是一场噩梦! - Ben

-1

您可以使用 JavaScript 代码 "window.location.origin",这将提供基本 URL,然后您可以添加 "/pathname"。


当某人重构Django的URL配置时会发生什么?用户界面中到处都是损坏的链接。 - Ben

-1

你不需要传递任何东西...

写。

 location.href = "/" + id

就这些了。


1
在被接受的答案中:document.location.href = url + "/" + id; 它不是基本上相同的想法吗? - Eric Aya
并不完全相同...而且它更短。那个也不太可能在永久JavaScript中运行。 - Rotimi Ayobami
当有人重构URL配置时会发生什么?界面上会出现大量的损坏链接。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接