Ответ 1
Предполагая, что вы используете django.views.static.serve
, он не похож на него, но создавая собственное представление, которое просто вызывает django.views.static.serve
, добавление заголовка Cache-Control должно быть довольно простым.
Есть ли простой способ отключить кэширование статических файлов на сервере разработки Django?
Я запускаю сервер со стандартной командой:
$ python manage.py runserver
У меня есть settings.py
, настроенный для обслуживания статических файлов из каталога /static
моего проекта Django. У меня также есть класс промежуточного программного обеспечения, который устанавливает заголовок Cache-Control
в must-revalidate, no-cache
для разработки, но это только влияет на URL-адреса, которые не находятся в моем каталоге /static
.
Предполагая, что вы используете django.views.static.serve
, он не похож на него, но создавая собственное представление, которое просто вызывает django.views.static.serve
, добавление заголовка Cache-Control должно быть довольно простым.
@Ответ Эрика Форсберга сработал у меня. Вот что я должен был сделать:
Прокомментируйте приложение staticfiles с INSTALLED_APPS
в settings.py
:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
#'django.contrib.staticfiles',
)
Оставьте мою переменную STATIC_URL
в settings.py
:
STATIC_URL = '/static/'
Добавить запись в мою базу проектов urls.py
:
# static files w/ no-cache headers
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}),
Обратите внимание, что я также устанавливаю заголовки Cache-Control
в классе промежуточного программного обеспечения nocache.py
:
class NoCache(object):
def process_response(self, request, response):
"""
set the "Cache-Control" header to "must-revalidate, no-cache"
"""
if request.path.startswith('/static/'):
response['Cache-Control'] = 'must-revalidate, no-cache'
return response
И затем включив это в settings.py
:
if DEBUG:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'nocache.NoCache',
)
Приложение Django contrib.staticfiles
автоматически обслуживает статические файлы, переопределяя команду runserver
. С этой конфигурацией вы не можете контролировать, как она обслуживает статические файлы.
Вы можете запретить приложению staticfiles обслуживать статические файлы, добавив параметр --nostatic
в команду runserver:
./manage.py runserver --nostatic
Затем вы можете написать конфигурацию URL, чтобы вручную обрабатывать статические файлы с заголовками, которые не позволяют браузеру кэшировать ответ:
from django.conf import settings
from django.contrib.staticfiles.views import serve as serve_static
from django.views.decorators.cache import never_cache
urlpatterns = patterns('', )
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', never_cache(serve_static)),
)
Если вы хотите, чтобы ваша команда manage.py runserver
по умолчанию --nostatic
опцию --nostatic
, вы можете поместить ее в ваш manage.py
:
if '--nostatic' not in sys.argv:
sys.argv.append('--nostatic')
Мое очень простое решение:
from django.contrib.staticfiles.views import serve
from django.views.decorators.cache import never_cache
static_view = never_cache(serve)
urlpatterns += static_view(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
В новых версиях Django очень простое решение - изменить URL проекта следующим образом:
from django.conf.urls.static import static
from django.contrib.staticfiles.views import serve
from django.views.decorators.cache import cache_control
# YOUR urlpatterns here...
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, view=cache_control(no_cache=True, must_revalidate=True)(serve))
Я пришел к этому, посмотрев, как staticfiles изменяет URL-адреса автоматически, и просто добавив декоратор представления. Я действительно не понимаю, почему это не по умолчанию, а только для разработки. Представление может правильно обрабатывать HTTP-заголовок "If-Modified-Since", поэтому запрос всегда выполняется, но содержимое передается только при изменениях (судя по просмотру метки времени изменения в файле).
Чтобы это работало, вы должны добавить --nostatic
при использовании runserver
, в противном случае вышеуказанные изменения просто игнорируются.
ВАЖНОЕ РЕДАКТИРОВАНИЕ: то, что у меня было раньше, не сработало, потому что я не использовал --nostatic
а декоратор never_cache
также включал в себя no-store
что означало, что неизмененные файлы всегда пересылались вместо возврата 304 Not Modified
Для более новых Django способ написания классов промежуточного программного обеспечения немного изменился.
Следуйте всем инструкциям из @aaronstacy выше, но для класса промежуточного программного обеспечения используйте это:
class NoCache(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
response['Cache-Control'] = 'must-revalidate, no-cache'
return response
Используйте whitenoise
. Существует много проблем со статическим обслуживанием файлов в runserver, и все они уже исправлены в whitenoise
. Это также ПУТЬ быстрее.
Они говорили о том, чтобы просто заменить встроенную статическую сервировку, но пока никто не обошел ее.
Шаги, чтобы использовать его в разработке...
Установите с помощью pip install whitenoise
Добавьте следующее в конец settings.py:
if DEBUG:
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware',
] + MIDDLEWARE
INSTALLED_APPS = [
'whitenoise.runserver_nostatic',
] + INSTALLED_APPS
Это не имеет ничего с Django, потому что ничего не изменилось после того, как я переустановил Django, используя pip.
Это поведение браузера, поэтому вам просто нужно очистить файлы кешированных изображений вашего браузера.
Это так просто, если вы используете Django 2. 0+
Шаг 1: Создайте django.contrib.staticfiles в качестве комментария в settings.py (уровень проекта)
INSTALLED_APPS = [
# 'django.contrib.staticfiles',
]
Шаг 2: Импортируйте подписки в urls.py (уровень проекта)
from django.conf.urls.static import static
from django.contrib.staticfiles.views import serve
from django.views.decorators.cache import never_cache
from . import settings
Шаг 3: Добавьте следующую строку в urls.py (уровень проекта) после urlpatterns
urlpatterns = [
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, view=never_cache(serve))
Убедитесь, что STATIC_URL объявлен в вашем settings.py
STATIC_URL = '/static/'