Сессии — это один из способов для сохранения данных пользователей между их запросами. Принцип работы сессий напоминает куки. Чтобы начать работать с сессиями, необходимо настроить секретный ключ. Для настройки и получения данных сессии используется объект session из пакета flask. Этот объект функционирует как словарь, но способен отслеживать изменения.

Данные в сессиях сохраняются в браузере в виде куки, которые и называются куки сессии. Однако, в отличие от обычных куки, Flask криптографически подписывает куки сессии, что позволяет всем видеть их содержимое, но не менять без секретного ключа. Как только сессии настроены, каждый следущий запрос проверяет подлинность куки с помощью указанного секретного ключа. Если идентификация не проходит, содержимое куки отклоняется и браузеру отправляются новые куки сессии.

Знакомые с PHP заметят отличия в подходе к сессиям: в PHP куки не хранят данные о сессии, а только ее ID, уникальную строку, которая связывает данные сессии на сервере. Во Flask данные хранятся в клиенте, и такой подход называют клиентскими сессиями.

По умолчанию, куки и клиентские сессии во Flask имеют немного различий. Их ограничения аналогичны:

  • Не подходят для хранения конфиденциальной информации (например, пароли).
  • Увеличивают нагрузку на каждый запрос.
  • Объем хранения ограничен 4 КБ.
  • Количество куки на один сайт ограничено.

и так далее.

Единственное отличие клиентских сессий – защита содержимого сессионных куки от изменений без секретного ключа.

Для работы с клиентскими сессиями во Flask можно либо создать собственный интерфейс сессий, либо воспользоваться расширениями такими как Flask-Session или Flask-KVSession.

Как читать, записывать и удалять данные сессии

Ниже приведен код, демонстрирующий процесс чтения, записи и удаления данных сессий. Откроем файл main2.py, чтобы добавить следующий код ниже функции представления article():

from flask import  Flask, render_template, request, redirect, url_for, flash, make_response, session
#...
@app.route('/visits-counter/')
def visits():
    if 'visits' in session:
	session['visits'] = session.get('visits') + 1  # чтение и обновление данных сессии
    else:
	session['visits'] = 1  # настройка данных сессии
    return "Total visits: {}".format(session.get('visits'))

@app.route('/delete-visits/')
def delete_visits():
    session.pop('visits', None)  # удаление данных о посещениях
    return 'Visits deleted'
#...

Здесь объект session функционирует как словарь. Если сервер еще не запущен, стоит это сделать и перейти на http://localhost:5000/visits-counter/. На странице будет отображаться счетчик посещений:

Сессии во Flask 1

Частое обновление страницы увеличит счетчик.

Сессии во Flask 12

Flask отправляет куки сессии клиенту только в случае создания новой сессии или изменений в существующей. При первом посещении http://localhost:5000/visits-counter/ сработает блок else, что приведет к созданию новой сессии и отправке куки клиенту. В дальнейшем http://localhost:5000/visits-counter будет вызывать код в блоке if, обновляющий счетчик visits в сессии. Изменение данных в сессии ведет к отправке обновленных куки.

Перейдите на http://localhost:5000/delete-visits/, чтобы удалить данные посещений.

Удаление данных сессии

Теперь переход на http://localhost:5000/visits-counter снова начнет счетчик с 1.

Сессии во Flask 1

По умолчанию, куки сессии активны до закрытия браузера. Чтобы продлить их действие, нужно задать атрибут permanent как True. В таком случае срок действия куки будет зависеть от значения атрибута permanent_session_lifetime, который имеет значение по умолчанию — 31 день. Этот период можно изменить, указав новое значение для ключа настройки PERMANENT_SESSION_LIFETIME.

import datetime

app = Flask(__name__)
app.permanent_session_lifetime = datetime.timedelta(days=365)
# app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=365)

Объект sessions доступен в шаблонах приложения, как и объект request.

Изменение данных сессии

Важно: прежде чем следовать инструкции, необходимо удалить куки, установленные локальным хостом.

В большинстве случаев объект session сам фиксирует изменения. Однако бывают ситуации, такие как изменения в структуре изменяемых данных, которые нужно фиксировать вручную, установив атрибут modified как True. В противном случае Flask не отправит изменения в куки клиенту. Ниже приведен код, показывающий, как это можно сделать. Откроем файл main2.py, чтобы добавить следующий фрагмент до функции представления delete_visits().

#...
@app.route('/session/')
def updating_session():
    res = str(session.items())

    cart_item = {'pineapples': '10', 'apples': '20', 'mangoes': '30'}
    if 'cart_item' in session:
	session['cart_item']['pineapples'] = '100'
	session.modified = True
    else:
	session['cart_item'] = cart_item

    return res
#...

Первый визит на http://localhost:5000/session/ активирует код в блоке else, создавая новую сессию с данными в виде словаря. После следующего посещения http://localhost:5000/session/, данные сессии обновляются с изменением количества «ананасов» до 100. Установка атрибута modified как True позволяет Flask отправить обновленные куки сессии клиенту.

Если сервер еще не запущен, его необходимо запустить и перейти на http://localhost:5000/session/. На странице отобразится пустой словарь session, поскольку браузер еще не отправил сессионные куки на сервер.

Все данные сессии во Flask 1

При обновлении страницы во второй раз «ананасы» будут установлены на 10:

Все данные сессии во Flask 2

Третье обновление покажет изменение значения до 100.

Объект сессии фиксирует изменение благодаря атрибуту modified. Убедитесь, что это так, удалив все установленные с ответственным значением True куки и закомментируйте строку. Теперь после первого запроса значение «ананасов» будет равно 10.

Это основное, что следует знать о сессиях во Flask. Имейте в виду, что по умолчанию сессии во Flask являются клиентскими.

Вопросы для самопроверки:

  1. Какую роль играет объект session из пакета flask в работе с сессиями?
  2. Что отличает сессионные куки Flask от обычных куки?
  3. Какие расширения могут быть использованы для работы с клиентскими сессиями во Flask?
  4. Как можно продлить срок действия сессионных куки во Flask?
  5. Почему важно удалить куки, установленные локальным хостом, прежде чем вносить изменения в данные сессии?