добавить параметр строки запроса в медиа-файл в форме администратора - PullRequest
0 голосов
/ 09 мая 2018

Я хотел бы добавить номер версии в файл javascript, определенный в классе Media формы администрирования django.

  class Media:    
        js = ['scripts/my_file.js?v=abc1234, ]

Но ... URL кодируется так, что '?' становится "% 3F".

Есть ли способ заставить django НЕ кодировать URL?

В качестве примечания, причина, по которой я это делаю, заключается в том, чтобы получить последний git commit моих статических файлов при загрузке сайта, добавив в файл настроек следующее:

STATIC_COMMIT = check_output(['git', 'log','-n', '1','--pretty=format:%h','--', os.path.join(BASE_DIR, 'my_app/static')]).decode("utf-8").strip()

Затем используйте следующее в классе Media:

js = [f'scripts/my_file.js?{settings.STATIC_COMMIT}', ]

Если я смогу это сделать, то мне никогда не придется вручную создавать версии медиафайлов или просить пользователей обновить кеш браузера, или, что хуже всего, неверный файл javascript (или css) запускается из кеша.

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

ОК, как я и думал, список медиа-файлов 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, а не к версионированию, дала вдохновение.

0 голосов
/ 07 декабря 2018

Если у вас есть глобальная версия статических файлов, вы можете исправить django.froms.widgets.Media.render() следующим образом:

from django.conf import settings
from django.forms.widgets import Media, MEDIA_TYPES

original_render = Media.render
def patched_render(self):
    result = original_render(self)
    for media_type in MEDIA_TYPES:
        result = result.replace('.%s' % media_type,
            '.%s?v=%s' % (media_type, settings.STATIC_RESOURCES_VERSION))
    return result
Media.render = patched_render
0 голосов
/ 09 мая 2018

Я бы сделал это следующим образом, поскольку, насколько я знаю, question mark ? не будет работать.

переопределит templates/admin/base_site.html и добавит ваш файл js + random_ID

{% extends "admin/base.html" %}

{% block extrahead %}
    <script type="text/javascript"></script>
{% endblock %}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...