Отключить кеширование статических файлов на сервере разработки Django

Есть ли простой способ отключить кеширование статических файлов на сервере разработки Django?

Запускаю сервер стандартной командой:

$ python manage.py runserver

У меня settings.py настроено обслуживание статических файлов из каталога /static моего проекта Django. У меня также есть класс промежуточного программного обеспечения, который устанавливает заголовок Cache-Control в must-revalidate, no-cache для разработки, но это влияет только на URL-адреса, которых нет в моем каталоге /static.


person aaronstacy    schedule 10.08.2011    source источник
comment
Сделать это поведение без кеширования по умолчанию было предметом этого тикета и было отложено в ожидании возможно слияние с белошумом (который уже решил эту проблему).   -  person Kevin Christopher Henry    schedule 13.11.2018
comment
Вы можете просто протестировать свои сайты в окно в режиме инкогнито. Кеши не сохранятся.   -  person Samy    schedule 27.11.2018


Ответы (10)


Предполагая, что вы используете django.views.static.serve, это не похоже, но написать собственное представление, которое просто вызывает django.views.static.serve, добавление заголовка Cache-Control должно быть довольно простым.

person Erik Forsberg    schedule 10.08.2011

Ответ @Erik Forsberg сработал для меня. Вот что мне пришлось сделать:

  • Закомментируйте приложение 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',
    )
person aaronstacy    schedule 10.08.2011
comment
Вы также можете сделать это, не отключая приложение staticfiles, запустив команду runserver с параметром --nostatic. Это помешает приложению staticfiles обслуживать статические файлы. См. Мой ответ для получения дополнительной информации. - person gitaarik; 15.08.2013
comment
Одна проблема, которую я заметил с этим подходом, - это некоторые приложения, такие как rest framework break, когда у них есть {% load staticfiles%} в их файлах шаблонов. Помимо этого, исправлена ​​проблема кеширования. - person Rajesh Chamarthi; 21.10.2015
comment
Как ни странно, я не смог заставить это работать. Firefox / Chrome, похоже, игнорируют управление кешем, Django не отправляет правильный заголовок. Единственный обходной путь, который я смог найти, - это добавить случайное число к URL-адресу носителя. - person Cerin; 10.03.2017
comment
Довольно сложно для того, что нужно добавить из коробки - person Vadorequest; 08.10.2018

Приложение contrib.staticfiles Django автоматически обслуживает статические файлы, переопределяя команду 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, вы можете поместить это в свой manage.py:

if '--nostatic' not in sys.argv:
    sys.argv.append('--nostatic')
person gitaarik    schedule 10.08.2013
comment
Это самое простое решение. - person zengr; 03.09.2014
comment
Кажется немного странным, что это необходимо; во время разработки (единственный раз, когда вы должны использовать runserver в соответствии с рекомендациями) вы действительно не хотите, чтобы что-то кешировалось, не так ли? Мне кажется, что поведение по умолчанию во время разработки должно быть never_cache и указывать необязательный аргумент, который включал бы кеширование для runserver. Поймите, здесь не место для предложений Django, но когда я исследовал эту тему, меня это просто поразило. - person Nick Spacek; 07.10.2014
comment
Этот ответ не всегда сработает. Его можно упростить и сделать более полезным. Если urlpatterns включает URL-адрес для приема всей почты домена в конце, это не сработает. Поэтому добавьте новый URL в начало urlpatterns. А если у вас STATIC_URL не установлено статическое значение, это не сработает. Так что используйте urlpatterns = static(settings.STATIC_URL, view=never_cache(serve_static)) + urlpatterns. (Функцию static можно найти в django.conf.urls.static.) - person nmgeek; 01.05.2016
comment
Некоторые команды manage.py не распознают флаг --nostatic. Обновление manage.py для использования и обновление, если оператор if sys.argv[1] == 'runserver' and '--nostatic' not in sys.argv: ... исправил это. - person Foot; 29.04.2021

Мое очень простое решение:

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)
person Vladislav    schedule 06.07.2012
comment
Хм. У меня это не работает. Я получаю эту ошибку: TypeError: serve() takes at least 2 arguments (1 given). Может, вы хотели вместо этого использовать django.conf.urls.static? Нравится: urlpatterns = static(settings.STATIC_URL, view=never_cache(serve)) + urlpatterns - person nmgeek; 01.05.2016

Используйте 1_. Есть много проблем со статическим файлом, обслуживаемым на сервере запуска, и все они уже исправлены в whitenoise. Это также НАМНОГО быстрее.

Они говорили о простой замене им встроенного статического обслуживания, но до этого еще никто не дошел.

Шаги по использованию в разработке ...

Установить с pip install whitenoise

Добавьте в конец settings.py следующее:

if DEBUG:
    MIDDLEWARE = [
        'whitenoise.middleware.WhiteNoiseMiddleware',
    ] + MIDDLEWARE
    INSTALLED_APPS = [
        'whitenoise.runserver_nostatic',
    ] + INSTALLED_APPS
person Tim Tisdall    schedule 03.04.2019

В более новых версиях Django очень простым решением является изменение URL-адресов проекта следующим образом:

from django.conf.urls.static import static
from django.contrib.staticfiles.views import serve
from django.views.decorators.cache import cache_control
from django.conf import settings

# 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

person Tim Tisdall    schedule 16.01.2019

Для более нового 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
person Clayton Gulick    schedule 29.08.2018

Это так просто, если вы используете 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/'
person Priyanshu Kumar    schedule 09.03.2019
comment
Это не позволяет Django отображать какие-либо статические файлы (изображения, CSS и т. Д.). - person Elendurwen; 09.12.2020

Приложение staticfiles реализует обслуживание статических файлов с помощью переопределение команды runserver. Мы можем сделать то же самое: снова переопределить эту команду и реализовать собственный обработчик, который отключает кеширование.

Обратите внимание, что ваше приложение django должно быть перед django.contrib.staticfiles в INSTALLED_APPS, иначе ваша команда будет проигнорирована.

# your_django_app/management/commands/runserver.py

from django.utils.cache import add_never_cache_headers
from django.contrib.staticfiles.handlers import (
    StaticFilesHandler as BaseStaticFilesHandler,
)
from django.contrib.staticfiles.management.commands.runserver import (
    Command as RunserverCommand,
)


class StaticFilesHandler(BaseStaticFilesHandler):
    def serve(self, request):
        response = super().serve(request)
        add_never_cache_headers(response)
        return response


class Command(RunserverCommand):
    def get_handler(self, *args, **options):
        handler = super().get_handler(*args, **options)

        # Check that serving static files is enabled
        if isinstance(handler, BaseStaticFilesHandler):
            # If yes, replace the original handler with our custom handler
            handler = StaticFilesHandler(handler.application)

        return handler
person andreymal    schedule 17.03.2021

Это не имеет ничего общего с Django, потому что ничего не изменилось после того, как я переустановил Django с помощью pip.

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

Ссылка

Chrome Очистите кеш и файлы cookie

person Simin Jie    schedule 21.12.2017
comment
Да, но ты не хочешь делать это каждые несколько секунд - person Elendurwen; 09.12.2020