Кэширование сайтов на Flask. Расширение Flask-Caching

Создано: 13.06.25

Кэширование позволяет сохранить результат выполнения функции (или скрипта) и при следующем ее вызове не выполнять ее снова, а возвращать ранее сохраненный результат. Такой механизм избавляет сервер от лишних вычислений. Обычно кэшируют на какое-то время. Однако в случае статического сайта на Flask для view-функций это можно делать "навсегда", то есть до перезапуска программного веб-сервера (при перезапуске сервера данные кэша теряются). Кэширование подходит не для всех функций.

Чтобы использовать кэширование во flask-приложении, следует дополнительно установить расширение Flask-Cashing:

$ pip install Flask-Caching

В приложении сначала задают конфигурацию кэширования, применить ее к экземпляру Flask, потом создать экземпляр Cache, через который происходит управление кэшем:

from flask_caching import Cache

config = {
    "DEBUG": True,          # some Flask specific configs
    "CACHE_TYPE": "SimpleCache",  # Flask-Caching related configs
    "CACHE_DEFAULT_TIMEOUT": 300
}
app = Flask(__name__)
# tell Flask to use the above defined config
app.config.from_mapping(config)
cache = Cache(app)

Другие способы установки кэша см. на сайте расширения Flask-Caching.

Время кэширования задается в секундах. Если требуется кэшировать без ограничения по времени (бесконечное хранение), то используется значение 0 (в коде выше вместо 300 следует написать 0). Когда ведется разработка приложения, и кэширование надо отключить, то можно указать время в 1 секунду.

Чтобы результат выполнения view-функции кэшировался, после декоратора роутера и перед ее заголовком надо указать декоратор кэширования:

@app.route('/')
@cache.cached()
def index():
    return render_template('index.html')

Если в настройках было задано время кэша по-умолчанию, и оно подходит для данной функции, то в скобках декоратора можно не указывать время. Иначе, это делается через параметр timeout. Например, @cache.cached(timeout=50).

Если кэшируется обычная функция (не представление страниц), то следует присваивать уникальное значение параметру key_prefix. По нему будет извлекаться результат выполнения функции из кэша (для view-функций роль ключей играют адреса). Его основная задача - предотвратить конфликты между различными функциями, которые используют кэширование.

@cache.cached(key_prefix='ads')
def ads():
    return ...

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

def nav(menu, file_name):
    return Markup(menu.replace(
        f'<li><a href="{file_name}">',
        f'<li autoscroll class="selected"><a href="{file_name}">'))

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

{% cache 0 %}
  {{ highlighter('htmlD', ' ... ') }}
{% endcache %}

Для очистки кэша используется метод clear экземпляра Cache. Например, можно создать view-функцию, ведущую на определенную страницу, в теле функции вызвать clear(). При переходе по адресу страницы, кэш будет очищаться.

@app.route('/clear')
def cache_clear():
    cache.clear()
    abort(404)