Pull to refresh

Как избежать кэширования медиа-файлов на сервере разработки Django

Когда ваше приложение Django разворачивается в общедоступной сети, его статические файлы обслуживаются непосредственно Apache или Nginx без какого-либо участия Django или вашего кода на Python. По крайней мере, это то, что должно происходить. Статические файлы — это таблицы стилей, образы, все, что находится на вашем сервере, что возвращается в ответ на запрос и не нуждается в динамической сборке. Apache или Nginx могут обслуживать эти файлы быстро, и могут справляться с проблемами кэширования, сообщая клиенту, когда у него уже есть текущая версия и нет необходимости загружать новую.

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

Часто возникает одна проблема, при изменении таблицы стилей или других статических ресурсов, вы обнаружите, что ваш браузер упорно держится за устаревшие, кэшированные версии. Сервер разработки Django, похоже, не знает, что файлы изменились. Хуже того, кажется, что время от времени происходит кэширование самих файлов, так как даже указание вашему браузеру перезагрузить страницу часто не обновляет кэш. Итак, теперь вы перезапускаете сервер разработки, как если бы это был Apache.

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

Веб-приложения, над которыми я работаю, находятся в каталогах под home/name__app, а их статические медиа-файлы хранятся в каталогах под home/name__app/static. Во-первых, ваш файл настроек должен определить местоположение ваших мультимедийных файлов. Вот минимальный пример:

DEBUG = True
TIME_ZONE = 'America/New_York'
LANGUAGE_CODE = 'en-us'
MEDIA_ROOT = 'home/name__app/static'
MIDDLEWARE_CLASSES = ("django.middleware.common.CommonMiddleware",)
ROOT_URLCONF = 'name__app.urls'
INSTALLED_APPS = ( 'name__app.a', 'name__app.b')

Ваш urls-файл должен направлять запросы на медиафайлы в функцию, которую мы напишем только для их обслуживания. Я называю эту функцию «serve» и храню ее в модуле «staticserve»:


[ Обычный импорт ]
urlpatterns = patterns('',
  [ routing for your webapps here ]
  (r'(.*.png)', 'webapps.staticserve.serve'),
  (r'(.*.css)', 'webapps.staticserve.serve'),
  [ add additional media types here ]
  )

А вот модуль staticserve:


from django.views.static import serve as staticserve
import webapps.settings as settings
def serve(request, what):
   response = staticserve(request, what,
              document_root=settings.MEDIA_ROOT)
   response['Cache-Control'] = 'no-cache'
   return response

Это все, что есть! Я просто использовал поставляемую Django функцию static.service, которая возвращает HttpResponse, и добавил заголовок без кэша. Обратите внимание, что простое использование no-cache с вашими динамическими видами не будет работать, потому что браузер делает отдельный запрос для каждого медиа-файла. Обычным методом является вызов django.views.static.service непосредственно из вашего url-файла; эти дополнительные запросы к медиафайлам будут идти непосредственно туда, а не к какому-либо из ваших представлений, и на них будет отвечать отдельный набор заголовков ответов.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.