尝试将 Django 表单字段呈现为 html 模板中脚本标记中的变量,但 javascript 不起作用

Trying to render a django form field as a variable in a script tag in an html template, but the javascript isn't working

我的问题很简单——我正在尝试将 django 表单中的表单字段渲染到 javascript 变量中,该变量在 django 模板中的 <script> 标记内定义。

当我输出一个CharField时,没有问题。但是,当我尝试呈现 ChoiceField 时,生成的输出会破坏 html,并阻止脚本标签正确解析我的变量。

为了演示我的设置,我在 forms.py 中定义了一个表单,与这个示例表单完全一样:

from django import forms
form = TestForm(forms.Form):
    testfield = forms.ChoiceField(initial="increase_rate", 
                                  choices=[
                                        ("a", "option a"),
                                        ("b", "option b"),
                                        ("c", "option c"),
                                        ("d", "option d")
                                  ])

我正在 views.py 中实例化表单,并将其传递到要呈现的 django 模板中。

from django.shortcuts import render
from .forms import TestForm

[...]

@require_http_methods(["GET"])
def webpage(request):
    form = TestForm()
    return render(request, 'index.html', {"form":form})

然后,最后,在我的模板中,我有如下内容:

[...]
<script>
    window.testfield = '{{ form.testfield }}'
</script>
[...]

到目前为止,一切正常。一点也不麻烦。但是当我将字段渲染到模板中并在我的浏览器中检查它时,我得到以下信息:

<script>
    window.testfield = '<select name="trigger" id="id_trigger">
  <option value="a" selected>option a</option>

  <option value="b">option b</option>

  <option value="c">option c</option>

  <option value="d">option d</option>

</select>'
</script>

此输出打破了 html,并防止脚本标记被解释为我想要的变量。这是一个主要问题,因为我想在页面的其他地方以编程方式重用这些。

我尝试了以下方法:

<script>
    window.testfield = '{{ form.testfield|escape }}'
</script>

但是还是没有成功。任何人都可以提供任何帮助,我们将不胜感激!

我正在积极研究解决方案。我目前的猜测是输出需要以某种我不理解的方式转义。我想模板标签和过滤器有我的答案,我只需要找到它。一旦找到解决方案,将post更新。

使用<script type="text/template"></script>

这样浏览器就知道它只是文本并会忽略它。

所以,我想通了。事实证明,问题是在 HTML.

解析标签时,白色 space、换行符和未转义的双引号 (") 的存在破坏了标签

所以我最终使用了以下内容:

{% spaceless %}
<script>
    window.testfield = '{{ form.testfield|addslashes }}'
</script>
{% endspaceless %}

它起作用了,允许我将 django 表单字段的字符串表示形式存储在 javascript 变量中。根据文档,{% spaceless %}“删除 HTML 标签之间的白色 space。这包括制表符和换行符。” [1].至于过滤器 |addslashes,它“在引号前添加斜线。对于转义 CSV 中的字符串很有用”[2]。在我的例子中,这两种解决方案都是必需的,因为没有它们,脚本标签就坏了。

至于为什么 |escape 过滤器不能单独工作,我不确定。阅读文档,似乎应该有。以下是 |escape 过滤器实际执行的操作 [3]:

Escapes a string’s HTML. Specifically, it makes these replacements:

< is converted to &lt;
> is converted to &gt;
' (single quote) is converted to &#x27;
" (double quote) is converted to &quot;
& is converted to &amp;

我只能猜测为什么这不起作用。我认为这是因为它对白色 space 没有任何作用。但我不应该推测。我欢迎您提出任何解释。一如既往,理解机器的思维方式比任何单一的、特定的解决方案都要好。谢谢。

[1] - https://docs.djangoproject.com/en/dev/ref/templates/builtins/#spaceless

[2] - https://docs.djangoproject.com/en/dev/ref/templates/builtins/#addslashes

[3] - https://docs.djangoproject.com/en/dev/ref/templates/builtins/#escape