Django: Как получить статический путь к файлу в среде разработки? - PullRequest
4 голосов
/ 22 февраля 2012

Сначала немного фона. Я использую следующую «хитрость» для предотвращения нежелательного кеширования браузером статических файлов (CSS, JS и т. Д.):

<script src="{{ STATIC_URL }}js/utils.js?version=1302983029"></script>

Когда строка версии изменяется при последующей загрузке страницы, браузер повторно выбирает статический файл с сервера. (Google "css caching" для статей об этой уловке.)

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

Для этого я использую время последнего изменения статического файла в качестве строки версии. Я делаю пользовательский тег шаблона для этого:

<script src="{% versioned_static 'js/utils.js' %}"></script>

А вот как работает шаблон тега:

import os.path
from django import template
from django.conf import settings

class VersionedStaticNode(template.Node):
    ...
    def render(self, context):
        # With the example above, self.path_string is "js/utils.js"
        static_file_path = os.path.join(settings.STATIC_ROOT, self.path_string)
        return '%s?version=%s' % (
            os.path.join(settings.STATIC_URL, self.path_string),
            int(os.path.getmtime(static_file_path))
            )

Чтобы узнать время последнего изменения статического файла, мне нужно знать его путь к файлу в системе. Я получаю этот путь к файлу, соединяя settings.STATIC_ROOT и относительный путь файла от этого статического корня. Это все хорошо для производственного сервера, так как все статические файлы собираются на STATIC_ROOT.

Однако на сервере разработки (где используется команда runserver manage.py) статические файлы не собираются в STATIC_ROOT. Так как же получить путь к файлу статического файла при запуске в разработке?

(Чтобы прояснить мою цель: ситуация с кэшированием, которую я хочу избежать, заключается в том, что браузер использует несоответствие нового HTML и старого CSS / JS. На производстве это может сильно запутать пользователей; в процессе разработки это может сбить меня с толку и других разработчиков и вынуждает нас часто обновлять страницы / очищать кеш браузера.)

1 Ответ

13 голосов
/ 22 февраля 2012

Если вы используете django.contrib.staticfiles, вот выдержка из команды findstatic (django / contrib / staticfiles / management / commands / findstatic.py), которая должна помочь. Для поиска файла используется finders.find .

    from django.contrib.staticfiles import finders

    result = finders.find(path, all=options['all'])

    path = smart_unicode(path)
    if result:
        if not isinstance(result, (list, tuple)):
            result = [result]
        output = u'\n  '.join(
            (smart_unicode(os.path.realpath(path)) for path in result))
        self.stdout.write(
            smart_str(u"Found '%s' here:\n  %s\n" % (path, output)))
...