Django的模板标签在javascript内部。

14

我的应用程序的urls.py是:

from django.urls import path
from . import views

app_name = 'javascript'
urlpatterns = [
    path('create_table', views.create_table, name='create_table')

我的views.py是:
def create_table(request):
    row_data = "this is row data"
    context = {'row_data': row_data}
    return render(request, 'javascript/create_table.html', context)

我的create_table.html文件是:
{% load static %}
<button id="create_table">Get data</button>
<div id="place_for_table"></div></div>
<script src="{% static 'javascript/scripts/create_table.js' %}"></script>

我的`create_table.js`文件是这样的:
function create_table() {
    document.getElementById("place_for_table").innerHTML = '{{ row_data }}';
}

document.getElementById("create_table").onclick = function() {
    create_table()
}

我想做的是在点击“create_table”按钮时运行create_table.js脚本,该脚本应在“place for table” div元素中显示“this is row data”文本。
然而,实际显示的只是“{{ row_data }}”。
我已经阅读了关于在Javascript中使用Django变量的其他类似问题,但根据我的理解,它们都建议按照我所做的方式进行操作,所以我不确定我做错了什么。
6个回答

7
如果您在模板中有一个要检测点击的元素,为什么不换一种方式,将上下文变量传递给JS函数呢?
<button onclick="create_table({{ row_data }})">Click me</button>

通过这样做,您可以检查页面以查看数据是否将被正确传递。您可能需要通过过滤器(例如escapejssafe)来传递数据。

或者您可以尝试以下方法:

{% load static %}

<button id="create_table">Get data</button>
<div id="place_for_table"></div></div>

<script type="text/javascript">
    var row_data = "{{ row_data }}";
</script>
<script src="{% static 'javascript/scripts/create_table.js' %}">
</script>

这种方法的问题在于变量的作用域,你可能不想全局声明变量,所以这可能是一种简单的方法,但不一定是最佳解决方案。

谢谢Mark,我尝试了你的替代方法,效果很好。然而,我在第一种方法上遇到了一些问题。显示的内容是“未定义”,就好像onclick ="create_table({{ row_data }})"没有正确地将参数传递给函数一样(我还修改了脚本中的create_table函数以接受参数)。这个脚本需要包含在模板中吗?还是可以保留在单独的文件中? - barciewicz
1
这是一个好的答案,只需记住在另一种方法中row_data在全局作用域中,随着代码变得更复杂并引入额外的变量,这可能更容易出现错误。 - bonidjukic
1
@barciewicz 我稍微更新了一下我的答案,以提供有关模板过滤器等的更多信息。不过bonidjukic是正确的——考虑使用JavaScript时变量的作用域。您可能不希望全局声明事物。 - markwalker_

5
当你写 {{ row_data }} 时,你使用的是Django特定的“语言”,称为Django模板语言,这意味着所提到的语法只能被Django模板“理解”。
你在做的是加载一个单独的JavaScript文件,在其中Django模板语法不起作用,因为当浏览器来评估该文件时,{{ row_data }} 将看起来像另一个字符串文字,而不是你期望的东西。
如果你直接将JavaScript示例嵌入到Django模板中,它应该可以工作。
或者你可以以某种方式将Django模板中可用的数据“引导”到外部JavaScript文件中,以下是我如何处理的方法:

create_table.html

<script src="{% static 'javascript/scripts/create_table.js' %}"></script>
<script type="text/javascript">
$(function() {
  var create_table = Object.create(create_table_module);
  create_table.init({
    row_data: '{{ row_data }}',
    ...
  });
});
</script>

注意:将上述代码包装在jQuery的.ready()函数中是可选的,但如果您已经在应用程序中使用jQuery,则这是一种简单的方法,可以确保在初始页面加载后DOM是安全的进行操作。

create_table.js

var create_table_module = (function($) {
  var Module = {
    init: function(opts) {
      // you have access to the object passed
      // to the `init` function from Django template
      console.log(opts.row_data)
    },
  };

  return Module;
})(jQuery);

注意:将jQuery实例传递给模块是可选的,这里只是为了举例说明如何将外部依赖项传递给模块。

哎呀,太糟糕了。我本以为用这种方法能够在不刷新页面的情况下创建整个HTML表格,并通过Django视图函数从网页中获取数据进行填充。在Django模板中编写此类表格的所有HTML代码会很笨拙。在这种情况下,使用AJAX是唯一的办法吗? - barciewicz
我已经更新了答案,并提供了一个更具体的例子,希望能有所帮助。 - bonidjukic

3
我所做的是将javascript/jquery包含在{% block scripts %}中,并使用以下Django特定数据:

`

 $.ajax({
   type:"GET",
   url: "/reserve/run/?ip={{ row_data }}",
   dataType: "html",
   async: true,
   }).done(function(response) {
     $("#Progress").hide();
     $('#clickid').attr('href','javascript:ClearFlag()');
     var win = window.open("", "MsgWindow");
     win.document.write(response);
   }); 

`


3
我找到了一个解决方案,避免额外输入之前所有的答案。
这有点hacky:
只需将你的myjavascriptfile.js转换为myjavascriptfile.js.html,并将代码包装在一个<script>...</script>标记中,然后在模板文件中使用include而不是链接它们。 myTemplate.html
    ....
    {% block js_footer %}
    {% include "my_app/myjavascriptfile.js.html" %}
    {% endblock js_footer %}

myjavascriptfile.js.html

<script type="text/javascript">
    console.log('the time now is {% now "Y m d H:i:s" %}');
    ...
</script>

0

不要将函数写在单独的JS文件中,而是在HTML页面的脚本标签中编写,这样它就可以使用Django模板语言。


0
你可以在中使用Django模板标签和过滤器。
例如,你可以将Hello传递给with标签的dj_val和upper过滤器,在index.html的中,然后在控制台上显示如下的Hello和HELLO:
{% "index.html" %}

<script>
{% with dj_val="Hello" %}
    console.log("{{ dj_val }}") # Hello
{% endwith %}

console.log("{{ "Hello"|upper }}") # HELLO
</script>

小心,你不能将JavaScript的js_val设置为Hello,并传递给with标签的dj_val和upper过滤器在index.html中的中,然后控制台上没有显示任何内容,如下所示:
{% "index.html" %}

<script>
let js_val = "Hello"

{% with dj_val=js_val %}
    console.log("{{ dj_val }}") # Nothing
{% endwith %}

console.log("{{ js_val|upper }}") # Nothing
</script>

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