Фон
У меня есть сайт под управлением Django 2.0 на AWS ElasticBeanstalk. У меня есть несколько просмотров на моем веб-сайте, для расчета которых требуется некоторое время, поэтому я подумал о том, чтобы изучить простое кэширование. Я выбрал LocMemCache, потому что он выглядел как самый быстрый в настройке, отвечающий моим потребностям. (Я использую AWS, поэтому использование Memcached, очевидно, требует ElastiCache, что увеличивает стоимость и требует дополнительных затрат на установку, которых я хотел избежать.)
Представления меняются не часто, и сайт не имеет большого трафика, поэтому я установил длинные таймауты для кешей. Есть три вида, где я включил кэширование:
- Отчет, созданный внутри шаблона & ndash; использует кэширование фрагментов шаблона
- Список местоположений, запрошенных AJAX и используемых в библиотеке JS & ndash; использует кеширование для каждого вида
- Динамически генерируемый двоичный файл для загрузки & ndash; использует кэширование для каждого вида
Кэширование настроено и прекрасно работает.
Данные, входящие в эти представления, добавляются и редактируются другими сотрудниками моей компании, которые используются для того, чтобы их изменения появлялись немедленно. Итак, чтобы ответить на такие вопросы, как «Я обновил эти данные, почему веб-страница не обновилась?» Я хотел создать кнопку «Очистить кэш сервера», доступную для персонала, для принудительного сброса кеша.
Кнопка настроена и работает. Он запрашивает представление, которое вызывает cache.clear()
из django.core.cache
. Я использовал подход кувалдой cache.clear()
, потому что способ указания кеша для отдельного представления в коде кажется немного неуклюжим и запутанным, поэтому подход «очистить все» казался адекватным. И, по крайней мере, он всегда должен «работать» в том смысле, что все данные снова загрузятся.
Проблема
Когда я использую кнопку для вызова cache.clear()
, он очищает только кэш фрагмента шаблона. Кажется, он не очищает кэши для каждого просмотра. Зачем?
Согласно Документация Django ,
Будьте осторожны с этим; clear()
удалит все из кэша, а не только ключи, установленные вашим приложением.
Так почему же это не касается кэшей для каждого просмотра? Разве предупреждение не указывает на то, что clear()
опасно конкретно , потому что это кувалда, и ничто не пощадили? Что мне не хватает?
Использует ли AWS какую-то специальную память, неуязвимую для такого рода отбраковки? (Если это так, то почему фрагменты шаблона успешно очищены?) Я заметил (и нахожу это интересным), что кэш остается даже после развертывания нового образа в той же среде.
Я мог бы перейти на использование кэширования базы данных, но я хотел бы понять, почему это не работает, поэтому мне не нужно отказываться от LocMemCache в качестве опции, которую можно использовать в будущем.
Я также мог бы переместить остальных для использования кэширования фрагмента шаблона, но если я когда-либо расширю кэширование для соответствия другим потребностям, я захочу использовать кэширование для каждого просмотра. Кроме того, это решение было бы далеко не идеальным для представления загрузки двоичных файлов.
settings.py
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
## 'LOCATION': '',
},
}
portfolio.html
(Кэш # 1 - фрагмент шаблона)
{% load static cache compress %}
...
<div id="total-portfolio-content">
{% cache 7200 portfolio %}{% include 'reports/total_portfolio/report_include.html' %}{% endcache %}
</div>
map/urls.py
(Кэш-память № 2 - для просмотра)
from django.conf.urls import include, url
app_name = 'map'
urlpatterns = [
## Yes, I know this uses the old-style url(). I have plans to upgrade the entire project.
url(r'^(?P<tg>[\w-]+)/data.geojson$',
cache_page(60 * 60 * 12)(
views.NamedGeoJSONLayerView.as_view(model=FacilityCoord)),
name='tg-data'),
]
resources/urls/__init__.py
(кэш # 3 - для просмотра)
from django.conf.urls import include, url
app_name = 'resources'
urlpatterns = [
url(r'^download/$',
cache_page(60 * 60 * 12)(
views.DownloadMetricXLSX.as_view()),
name='download'),
]
myadmin/views.py
(кнопка очистки кэша)
from django.core.cache import cache
@staff_member_required(login_url=login_url)
def clear_cache(request):
cache.clear()
## And because that doesn't seem to work as advertised, I also tried....
## taken from <https://djangosnippets.org/snippets/1080/>
try:
cache._cache.clear() # in-memory caching
cache._expire_info.clear()
except AttributeError:
# I think this only applies to filesystem caching? Just grasping at straws.
old_freq = cache._cull_frequency
old_max = cache._max_entries
cache._max_entries = 0
cache._cull_frequency = 1
cache._cull()
cache._cull_frequency = old_freq
cache._max_entries = old_max
return JsonResponse({'success': True})