Управление версиями статических файлов с помощью Django - PullRequest
5 голосов
/ 12 мая 2011

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

В основном у меня есть тег шаблона, и я делаю что-то вроде

<script type="text/javascript" src="{{ MEDIA_URL }}{% versioned "javascript/c/c.js" %}"></script>

, который станет

<script type="text/javascript" src="http://x.com/media/javascript/c/c.min.js?123456"></script>.

Тег шаблона открывает файл javascript/c/c.js.v, где он находит номер версии и добавляет его в строку запроса. Версия генерируется сценарием оболочки (пока запускается вручную, вероятно, добавит хук предварительной фиксации), который проверяет, изменился ли файл (с помощью git diff).

Это все нормально работает, КРОМЕ:

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

Как лучше подходить к управлению версиями файлов?

В качестве альтернативы я подумываю заменить тег шаблона промежуточным программным обеспечением, которое изменяет все ссылки перед возвратом ответа. Это лучше, чем тег шаблона, который может быть ошибочно опущен. Но все еще не решает проблему изображений, на которые ссылаются из CSS.

Кроме того, я знаю, что наличие версии как части строки запроса может вызвать проблемы с некоторыми прокси-серверами, не кэширующими файл - поэтому я считаю целесообразным сделать версию частью имени файла - например, javascript/c/c.123456.js.

Примечание. Похоже, что с помощью Django невозможно решить эту проблему (очевидно, поскольку я даже не обслуживаю CSS через Django). Но должно быть решение, возможно, включающее некоторые уловки nginx.

Ответы [ 5 ]

1 голос
/ 20 мая 2013

Активы таблицы стилей

Для ваших активов, на которые ссылаются таблицы стилей, вам гораздо лучше использовать Sass & Compass.В Compass есть миксин, который автоматически добавит параметры запроса версии в конец статического ресурса, на который есть ссылка в таблице стилей.Номер версии изменяется только при перестроении таблицы стилей (что тривиально с compass watch при локальной разработке).

Ресурсы шаблонов

Для других файлов я хотел бына самом деле используется какой-то пост-потягивающий хук, который переписывает модуль Python, единственная цель которого - содержать текущую версию.

/var/www/aweso.me/
    ./files/
    ./private-files/
    ./static/
    ./project/
        ./manage.py
        ./fabfile.py
        ./.gitignore
        ./base/
            ./__init__.py
            ./wsgi.py
            ./settings/
                ./__init__.py
                ./modules
                    ./__init__.py
                    ./users.py
                    ./email.py
                    ./beta.py
                    ./redis.py
                    ./haystack.py
                ./version.py
                ./default.py
                ./local.py
                ./live.py

Ваш пост-пулл-крюк создаст:

/var/www/aweso.me/project/base/settings/version.py

Который будет содержать самый последний (или предыдущий) хеш git commit:

__version__ = "0763j34bf"

Затем с простым from .version import __version__ as ApplicationVersion в вашем settings.live ваш тег шаблона может просто использовать from settings import ApplicationVersion, чтобы записать этот параметр запроса каккэш-бастер.

0 голосов
/ 09 июня 2011

Я думаю, что простое решение может быть:

  1. Напишите ваши CSS-файлы в качестве шаблонов Django.
  2. Напишите команду Django для рендеринга ваших css-шаблонов (и сохраните их в доступном месте)
  3. В вашем сценарии развертывания вызовите эту команду.
0 голосов
/ 16 мая 2011

Добавит еще один шаг в мой сценарий предварительной фиксации, чтобы заменить все прямые ссылки ссылками на версионные файлы в свернутом CSS.

Похоже, лучшего способа сделать это не существует.Если вы думаете о чем-либо, дайте мне знать, и я рассмотрю вопрос об этом ответе.

Спасибо за ваши комментарии!

0 голосов
/ 09 июня 2011

Это также может помочь: http://www.fanstatic.org/

0 голосов
/ 12 мая 2011

Мы используем этот простой тег шаблона для генерации номера версии на основе времени изменения файла:

import os
import posixpath
import stat
import urllib

from django import template
from django.conf import settings
from django.contrib.staticfiles import finders

register = template.Library()

@register.simple_tag
def staticfile(path):
    normalized_path = posixpath.normpath(urllib.unquote(path)).lstrip('/')
    absolute_path = finders.find(normalized_path)
    if not absolute_path and getattr(settings, 'STATIC_ROOT', None):
        absolute_path = os.path.join(settings.STATIC_ROOT, path)
    if absolute_path:
        return '%s%s?v=%s' % (settings.STATIC_URL, path, os.stat(absolute_path)[stat.ST_MTIME])
    return path

Для версии до 1.3 Django существует еще более простая версия этого тега:

@register.simple_tag
def staticfile(path):
    file_path = os.path.join(settings.MEDIA_ROOT, path)
    url = '%s%s?v=%s' % (settings.MEDIA_URL, path, os.stat(file_path)[stat.ST_MTIME])
    return url

Использование:

<link rel="stylesheet" href="{%  staticfile "css/style.css" %}" type="text/css" media="screen" />
...