将Javascript添加到自定义小部件

5xu*_*xum 6 javascript python django jquery django-custom-field

这个问题与

Django:将Javascript添加到自定义小部件的最佳方法

但是不一样。

最初的问题询问如何向自定义django小部件中添加支持的javascript,答案是使用forms.Media,但是该解决方案对我不起作用。我的例子是这样的:

在以表单呈现时,该小部件会创建一条类似于(玩具示例)的线:

<div id="some-generated-id">Text here</div>
Run Code Online (Sandbox Code Playgroud)

现在,我还想添加到输出中的是另一行,如下所示:

<script>
$('#some-generated-id').datetimepicker(some-generated-options)
</script>
Run Code Online (Sandbox Code Playgroud)

最初的想法是,当小部件被呈现,无论是divscript得到呈现,但不起作用。问题在于html文档的结构如下所示:

-body
    - my widget
    - my widget's javascript
-script
    -calls to static files (jQuery, datetimepicker,...)
Run Code Online (Sandbox Code Playgroud)

在将小部件的javascript代码加载到浏览器中时,尚未加载jQuery和datetimepicker js文件(它们在文档末尾加载)。

我无法使用来执行此操作Media,因为我生成的选项和ID对函数至关重要。解决此问题的最佳方法是什么?

Rei*_*ica 5

文档

资产插入 DOM 的顺序通常很重要。例如,您可能有一个依赖于 jQuery 的脚本。因此,组合 Media 对象试图保留在每个 Media 类中定义资产的相对顺序。

考虑这个例子:

class FooWidget(forms.TextInput):
    class Media:
        js = ('foo.js',)

class BarWidget(forms.TextInput):
    class Media:
        js = ('bar.js',)

class SomeForm(forms.Form):
    field1 = forms.CharField(widget=BarWidget)
    field2 = forms.CharField(widget=FooWidget)

    def __init__(self, *args, **kwargs):
        super(SearchForm, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

现在,当您调用 时form.media,脚本将呈现如下:

<script type="text/javascript" src="/static/bar.js"></script>
<script type="text/javascript" src="/static/foo.js"></script>
Run Code Online (Sandbox Code Playgroud)

为什么bar.js渲染之前foo.js?因为 django 根据它们在表单中被调用的顺序来呈现它们,而不是定义类的顺序。如果你想改变这个例子中的顺序,只需交换位置field1field2in SomeForm

这对您使用 jQuery 有何帮助?您可以通过自定义小部件呈现您的 jQuery CDN 脚本:

class FooWidget(forms.TextInput):
    class Media:
        js = ('https://code.jquery.com/jquery-3.4.1.js', 'foo.js',)

class BarWidget(forms.TextInput):
    class Media:
        js = ('https://code.jquery.com/jquery-3.4.1.js', 'bar.js',)
Run Code Online (Sandbox Code Playgroud)

现在你form.media会看起来像这样:

<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<script type="text/javascript" src="/static/bar.js"></script>
<script type="text/javascript" src="/static/foo.js"></script>
Run Code Online (Sandbox Code Playgroud)

请注意如何/static/没有附加到 jQuery CDN?这是因为该.media属性检查给定的文件路径是否包含httphttps,并且仅将您的STATIC_URL设置附加到相对的文件路径。

还要注意,重复的文件名会被自动删除,所以我认为https://code.jquery.com/jquery-3.4.1.js每个需要它的小部件的开头包含一个是很好的做法。这样,无论您以何种顺序呈现它们,jQuery 脚本都将始终出现在需要它的文件之前。

附带说明一下,在文件名中包含数字时我会很小心。作为 Django 2.2,在尝试订购脚本时似乎存在错误。

例如:

class FooWidget(forms.TextInput):
    class Media:
        js = ('foo1.js', 'foo2.js',)

class BarWidget(forms.TextInput):
    class Media:
        js = ('bar1.js', 'bar13.js',)

class SomeForm(forms.Form):
    field1 = forms.CharField(widget=BarWidget)
    field2 = forms.CharField(widget=FooWidget)

    def __init__(self, *args, **kwargs):
        super(SearchForm, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

看起来像:

<script type="text/javascript" src="/static/bar1.js"></script>
<script type="text/javascript" src="/static/foo1.js"></script>
<script type="text/javascript" src="/static/bar13.js"></script>
<script type="text/javascript" src="/static/foo2.js"></script>
Run Code Online (Sandbox Code Playgroud)

我尝试了包含数字的名称的各种组合,但我无法遵循逻辑,所以我认为这是一个错误。