表单中的 Django 媒体资产,如何延迟/异步 JS 资产

问题描述

official docs 解释了如何为某些小部件自动添加资产。,来自他们的示例:

from django import forms

class CalendarWidget(forms.TextInput):
    class Media:
        css = {
            'all': ('pretty.css',)
        }
        js = ('animations.js','actions.js')

它没有描述的是如何使JS资产延迟或异步加载,例如

    <script defer src="https://myserver.com/static/animations.js">/script>

解决方法

您可以覆盖小部件的 js-renderer:

forms.py

def render_js(cls):
    return [
        format_html(
            '<script defer src="{}"></script>',cls.absolute_path(path)
        ) for path in cls._js
    ]
forms.widgets.Media.render_js = render_js

但是,它将与您应用程序的所有小部件相关。

UPD: 但是,如果您需要为每个 Widget 进行不同的渲染,我可以建议您使用以下技巧(使用 'private' 属性来定义格式):

class CalendarWidget(forms.TextInput):
    class Media:
        css = {
            'all': ('pretty.css',)
        }
        js = ('animations.js','actions.js','defer')

def render_js(cls):
    fmt = '<script src="{}"></script>'
    formats = {
        'defer': '<script defer src="{}"></script>'
    }

    for path in cls._js:
        if path in formats:
            fmt = formats[path]
            break

    return [
        format_html(
            fmt,cls.absolute_path(path)
        ) for path in cls._js if path not in formats
    ]
forms.widgets.Media.render_js = render_js