ОК, как я и думал, список медиа-файлов js сводится к заполнению шаблона с использованием функции django.forms.widget
def render_js(self):
return [
format_html(
'<script type="text/javascript" src="{}"></script>',
self.absolute_path(path)
) for path in self._js
]
В глубине работы absolute_path
есть вызов функции django.templatetags.static.static
, которая выполняет кодировку, которая уничтожает '?' пометить строку запроса.
Итак, я создал класс VersionedMediaJS
с пользовательским методом render_js
, который вместо того, чтобы касаться сложных вещей, просто добавляет версию:
class VersionedMediaJS():
def __init__(self, path, version):
self.path = forms.widgets.Media.absolute_path(None, path)
self.version = version
def render(self):
html = '<script type="text/javascript" src="{0}?v={1}"></script>'
return format_html(html, mark_safe(self.path), self.version)
@staticmethod
def render_js(media_object):
html = []
for path in media_object._js:
if hasattr(path, 'version'):
html.append(path.render())
else:
html.append(format_html('<script type="text/javascript" src="{0}"></script>', media_object.absolute_path(path)))
return html
forms.widgets.Media.render_js = VersionedMediaJS.render_js
В моем классе Media теперь я могу передать объект VersionedMediaJS()
в дополнение к обычным строковым файлам следующим образом:
class Media():
from django.conf import settings
js = ["scripts/whatever.js",
VersionedMediaJS('scripts/important.js',settings.SOURCE_COMMIT_STATIC_FILES_REV),
VersionedMediaJS('scripts/another.js','1.2')]
В результате в шаблон будет вставлено следующее:
<script type="text/javascript" src="/static/scripts/whatever.js"></script>
<script type="text/javascript" src="/static/scripts/important.js?v=50cdbe0"></script>
<script type="text/javascript" src="/static/scripts/another.js?v=1.2"></script>
Поскольку я управляю номером своей версии с помощью git commit, каждый раз, когда новый файл javascript фиксируется (или, точнее, передается на мой сервер prod), версия автоматически изменяется.
Я мог бы сделать то же самое для файлов CSS, но я не делал этого здесь.
Особая благодарность: dmpayton / django-embedded-media , которая, при непосредственном обращении к встраиванию скриптов и css, а не к версионированию, дала вдохновение.