• 3.1
  • 3.2
  • 6.1
  • Версия документации: 5.0

Как использовать сессии

Django полностью поддерживает сессии для анонимных пользователей, позволяет сохранять и получать данные для каждой посетителя сайта. Механизм сессии сохраняет данные на сервере и самостоятельно управляет сессионными куками. Куки содержат ID сессии, а не сами данные (если только вы не используете бэкенд на основе кук).

Активируем сессии

Сессии реализованы через промежуточный слой.

Чтобы активировать сессии, выполните следующие действия:

  • Убедитесь, что MIDDLEWARE_CLASSES содержит 'django.contrib.sessions.middleware.SessionMiddleware'. settings.py по умолчанию, созданный django-admin startproject, уже содержит SessionMiddleware.

Если вы не собираетесь использовать сессии, вы можете удалить SessionMiddleware из MIDDLEWARE_CLASSES и 'django.contrib.sessions' из INSTALLED_APPS. Это немного повысит производительность.

Настройка сессий

По умолчанию, Django хранит сессии в базе данных (используя модель django.contrib.sessions.models.Session). В некоторых случаях лучше хранить данные сессии в других хранилищах, поэтому Django позволяет использовать файловую систему или кэш.

Использование базы данных для хранения сессии

Если вы хотите использовать базу данных для хранения сессии, укажите 'django.contrib.sessions' в настройке INSTALLED_APPS.

После настройки выполните manage.py migrate, чтобы добавить таблицу в базу данных.

Использование кэша для хранения сессии

Для улучшения производительности вы можете использовать кэш для хранения сессии.

Для этого вы должны настроить кэш, смотрите раздел о кэше.

Предупреждение

Сеансы на основе кэша следует использовать только в том случае, если вы используете серверную часть кэша Memcached или Redis. Серверная часть кэша в локальной памяти не сохраняет данные достаточно долго, чтобы быть хорошим выбором, и будет быстрее использовать сеансы файлов или баз данных напрямую, вместо того, чтобы отправлять все через серверные части кэша файлов или базы данных. Кроме того, серверная часть кэша локальной памяти НЕ является многопроцессорной, поэтому, вероятно, не является хорошим выбором для производственных сред.

Если вы указали несколько кэшей в CACHES, Django будет использовать кэш по умолчанию. Чтобы использовать другой кэш, укажите его название в SESSION_CACHE_ALIAS.

После настройки кеша вам придется выбирать между кешем на базе базы данных или непостоянным кешем.

Серверная часть кэшированной базы данных (cached_db) использует кеш со сквозной записью — записи сеанса применяются как к базе данных, так и к кешу, именно в этом порядке. Если запись в кеш не удалась, исключение обрабатывается и регистрируется через регистратор сеансов, чтобы избежать сбоя в противном случае успешной операции записи.

Changed in Django 5.1:

Добавлена ​​обработка и протоколирование исключений при записи в кэш.

При чтении сеанса используется кеш или база данных, если данные были удалены из кеша. Чтобы использовать этот бэкэнд, установите для SESSION_ENGINE значение "django.contrib.sessions.backends.cached_db" и следуйте инструкциям по настройке для ``использования сеансов с поддержкой базы данных`_.

Серверная часть кэша («кэш») хранит данные сеанса только в вашем кэше. Это быстрее, поскольку позволяет избежать сохранения базы данных, но вам придется учитывать, что произойдет, когда данные из кэша будут удалены. Выселение может произойти, если кэш заполнится или сервер кэша будет перезапущен, и это будет означать потерю данных сеанса, включая выход пользователей из системы. Чтобы использовать этот бэкэнд, установите для SESSION_ENGINE значение "django.contrib.sessions.backends.cache".

Серверную часть кэша можно сделать постоянной, используя постоянный кэш, например Redis, с соответствующей настройкой. Но если ваш кеш определенно не настроен на достаточную устойчивость, выберите серверную часть кэшированной базы данных. Это позволяет избежать крайних случаев, вызванных ненадежным хранением данных в рабочей среде.

Использование файловой системы для хранения сессии

Чтобы использовать файловую систему, укажите "django.contrib.sessions.backends.file" в SESSION_ENGINE.

Вы также можете установить параметр SESSION_FILE_PATH (который по умолчанию выводит данные из tempfile.gettempdir(), скорее всего /tmp), чтобы контролировать, где Django хранит файлы сеансов. Обязательно проверьте, есть ли у вашего веб-сервера разрешения на чтение и запись в это место.

Использование сессии в представлениях

Когда SessionMiddleware активный, каждый объект HttpRequest – первый аргумент представления в Django – будет содержать атрибут session, который является объектом с интерфейсом словаря.

Вы можете читать и менять request.session в любом месте вашего представления множество раз.

class backends.base.SessionBase

Это базовый класс для всех объектов сессии. Он предоставляет набор стандартных методов словаря:

__getitem__(key)

Например: fav_color = request.session['fav_color']

__setitem__(key, value)

Например: request.session['fav_color'] = 'blue'

__delitem__(key)

Например: del request.session['fav_color']. Вызовет KeyError, если key ещё не в сессии.

__contains__(key)

Например: 'fav_color' in request.session

get(key, default=None)
aget(key, default=None)

Асинхронная версия: aget()

Например: fav_color = request.session.get('fav_color', 'red')

Changed in Django 5.1:

Добавлена ​​функция aget().

aset(key, value)
New in Django 5.1.

Пример: await request.session.aset('fav_color', 'red')

update(dict)
aupdate(dict)

Асинхронная версия: aupdate()

Пример: request.session.update({'fav_color': 'red'})

Changed in Django 5.1:

Добавлена ​​функция aupdate().

pop(key, default=__not_given)
apop(key, default=__not_given)

Асинхронная версия: apop()

Например: fav_color = request.session.pop('fav_color')

Changed in Django 5.1:

Добавлена ​​функция apop().

keys()
akeys()

Асинхронная версия: keys()

Changed in Django 5.1:

Добавлена ​​функция keys().

values()
avalues()

Асинхронная версия: avalues()

Changed in Django 5.1:

Добавлена ​​функция avalues().

has_key(key)
ahas_key(key)

Асинхронная версия: ahas_key()

Changed in Django 5.1:

Добавлена ​​функция ahas_key().

items()
aitems()

Асинхронная версия: aitems()

Changed in Django 5.1:

Добавлена ​​функция aitems().

setdefault()
asetdefault()

Асинхронная версия: asetdefault()

Changed in Django 5.1:

Добавлена ​​функция asetdefault().

clear()

Также содержит следующие методы:

flush()
aflush()

Асинхронная версия: aflush()

Удаляет данные текущей сессии и сессионную куку. Можно использовать, если необходимо убедиться, что старые данные не доступны с браузера пользователя (например, функция django.contrib.auth.logout() вызывает этот метод).

Changed in Django 5.1:

Добавлена ​​функция aflush().

Асинхронная версия: aset_test_cookie()

Устанавливает тестовую куку, чтобы проверить, что браузер пользователя поддерживает куки. Из-за особенностей работы кук вы не сможете проверить тестовую куку, пока пользователь не запросит следующую страницу. Подробности смотрите ниже (Setting test cookies).

Changed in Django 5.1:

Добавлена ​​функция aset_test_cookie().

Асинхронная версия: atest_cookie_worked()

Возвращает либо True, либо False, в зависимости от того, принял ли браузер пользователя тестовый файл cookie. Из-за особенностей работы файлов cookie вам придется вызывать set_test_cookie() или aset_test_cookie() при предыдущем запросе отдельной страницы. Дополнительную информацию см. в разделе «Настройка тестовых файлов cookie» ниже.

Changed in Django 5.1:

Добавлена ​​функция atest_cookie_worked().

Асинхронная версия: adelete_test_cookie()

Удаляет тестовую куку. Используйте, чтобы убрать за собой.

Changed in Django 5.1:

Добавлена ​​функция adelete_test_cookie().

Возвращает значение параметра SESSION_COOKIE_AGE. Это можно переопределить в пользовательском бэкэнде сеанса.

set_expiry(value)
aset_expiry(value)

Асинхронная версия: aset_expiry()

Указывает время жизни сессии. Вы можете передать различные значения:

  • Если value целое число, сессия истечет после указанного количества секунд неактивности пользователя. Например, request.session.set_expiry(300) установит время жизни равное 5 минутам.

  • Если value является объектом datetime или timedelta, срок действия сеанса истечет в эту конкретную дату/время.

  • Если value равно 0, срок действия файла cookie сеанса пользователя истечет при закрытии веб-браузера пользователя.

  • Если value равно None, сессия будет использовать глобальное поведение.

Чтение сессии не обновляет время жизни сессии. Время жизни просчитывается с момента последнего изменения.

Changed in Django 5.1:

Добавлена ​​функция aset_expiry().

get_expiry_age()
aget_expiry_age()

Асинхронная версия: aget_expiry_age()

Возвращает время в секундах до окончания действия сессии. Для сессий без времени окончания (или для тех, что действуют пока работает браузер), значение будет равно SESSION_COOKIE_AGE.

Функция понимает два необязательных именованных аргумента:

  • modification: время последнего изменения сессии в виде объекта datetime. По умолчанию соответствует текущему времени.

  • expiry: информация об истечении срока действия сеанса в виде объекта datetime, int (в секундах) или None. По умолчанию используется значение, сохраненное в сеансе с помощью set_expiry()/aset_expiry(), если оно есть, или None.

Примечание

Этот метод используется серверными модулями сеанса для определения срока истечения сеанса в секундах при его сохранении. На самом деле он не предназначен для использования вне этого контекста.

В частности, хотя возможно определить оставшееся время жизни сеанса только тогда, когда у вас есть правильное значение modification и expiry установлен как объект datetime, где у вас есть значение modification, проще вычислить срок действия вручную:

expires_at = modification + timedelta(seconds=settings.SESSION_COOKIE_AGE)
Changed in Django 5.1:

Добавлена ​​функция aget_expiry_age().

get_expiry_date()
aget_expiry_date()

Асинхронная версия: aget_expiry_date()

Возвращает дату окончания действия сессии. Для сессий, у которых дата завершения не указана (или которые завершаются при закрытии браузера), значением будет дата, отстоящая на SESSION_COOKIE_AGE секунд от текущего момента.

Эта функция принимает те же ключевые аргументы, что и get_expiry_age(), и применяются аналогичные примечания по использованию.

Changed in Django 5.1:

Добавлена ​​функция aget_expiry_date().

get_expire_at_browser_close()
aget_expire_at_browser_close()

Асинхронная версия: aget_expire_at_browser_close()

Возвращает либо True, либо False, в зависимости от того, истечет ли срок действия файла cookie сеанса пользователя при закрытии веб-браузера пользователя.

Changed in Django 5.1:

Добавлена ​​функция aget_expire_at_browser_close().

clear_expired()
aclear_expired()

Асинхронная версия: clear_expired()

Удаляет просроченные сессии из хранилища сессий. Этот метод класса используется clearsessions.

Changed in Django 5.1:

Добавлена ​​функция clear_expired().

cycle_key()
acycle_key()

Асинхронная версия: acycle_key()

Создает новый ключ сессии при сохранении текущих данных в ней. Функция django.contrib.auth.login() вызывает этот метод, чтобы противодействовать фиксации сессии.

Changed in Django 5.1:

Добавлена ​​функция acycle_key().

Сериализация сессии

Данная атака может быть смягчена, если выполнять сериализацию данных сессии с помощью JSON вместо pickle. Для этого в Django 1.5.3 добавили параметр SESSION_SERIALIZER, определяющий метод сериализации сессии. В целях обратной совместимости, по умолчанию параметр указывает на django.contrib.sessions.serializers.PickleSerializer в Django 1.5.x, но для укрепления безопасности, начиная с Django 1.6, установлен в django.contrib.sessions.serializers.JSONSerializer. Даже принимая во внимание предостережения из Реализация своего сериализатора, мы настоятельно рекомендуем использовать JSON сериализацию особенно при использовании кук в качестве хранилища сессии.

Например, вот сценарий атаки, если вы используете pickle для сериализации данных сеанса. Если вы используете подписанный сервер сеанса cookie и SECRET_KEY (или любой ключ SECRET_KEY_FALLBACKS) известен злоумышленнику (в Django нет встроенной уязвимости, которая могла бы привести к его утечке), злоумышленник может вставить в свой сеанс строку, которая, если ее не расшифровать, выполняет произвольный код на сервер. Техника выполнения этого проста и легко доступна в Интернете. Хотя хранилище сеансов файлов cookie подписывает данные, хранящиеся в файлах cookie, чтобы предотвратить несанкционированный доступ, утечка SECRET_KEY немедленно перерастает в уязвимость удаленного выполнения кода.

Поставляемые сериализации

class serializers.JSONSerializer

Обёртка над JSON сериализатором из django.core.signing. Может сериализовать только простые типы данных.

Кроме того, поскольку JSON поддерживает только строковые ключи, обратите внимание, что использование нестроковых ключей в request.session не будет работать должным образом:

>>> # initial assignment
>>> request.session[0] = "bar"
>>> # subsequent requests following serialization & deserialization
>>> # of session data
>>> request.session[0]  # KeyError
>>> request.session["0"]
'bar'

Аналогично, данные, которые не могут быть закодированы в JSON, например байты, отличные от UTF8, такие как '\xd9' (которые вызывают UnicodeDecodeError), не могут быть сохранены.

Обратитесь к разделу Реализация своего сериализатора для получения подробностей по возможностям сериализации в JSON.

Реализация своего сериализатора

Обратите внимание, что JSONSerializer не может обрабатывать произвольные типы данных Python. Как это часто бывает, приходится выбирать между удобством и безопасностью. Если вы хотите хранить более сложные типы данных, включая datetime и Decimal, в сеансах с поддержкой JSON, вам нужно будет написать собственный сериализатор (или преобразовать такие значения в сериализуемый объект JSON перед сохранением их в request.session). Хотя сериализация этих значений зачастую проста (DjangoJSONEncoder может оказаться полезным), написание декодера, который может надежно вернуть то же самое, что вы вставили, является более хрупким. Например, вы рискуете вернуть datetime, которое на самом деле было строкой, которая случайно оказалась в том же формате, который был выбран для datetimes).

Класс вашего сериализатора должен реализовать два метода: dumps(self, obj) и loads(self, data), для кодирования и декодирования словаря данных сессии соответственно.

Рекомендации для объекта сессии

  • Используйте обычные строки Python в качестве ключей словаря в request.session. Это больше соглашение, чем правило.

  • Ключи словаря сессии, которые начинаются с подчёркивания зарезервированы для внутреннего использования Django.

  • Не перекрывайте request.session новым объектом, не меняйте его атрибута. Пользуйтесь им как обычным словарём Python.

Примеры

Простейшее представление устанавливает переменную has_commented в True после того, как пользователь отправит комментарий. Это не позволяет пользователю отправлять комментарий более одного раза:

def post_comment(request, new_comment):
    if request.session.get("has_commented", False):
        return HttpResponse("You've already commented.")
    c = comments.Comment(comment=new_comment)
    c.save()
    request.session["has_commented"] = True
    return HttpResponse("Thanks for your comment!")

Это простейшее представление авторизует пользователя сайта:

def login(request):
    m = Member.objects.get(username=request.POST["username"])
    if m.check_password(request.POST["password"]):
        request.session["member_id"] = m.id
        return HttpResponse("You're logged in.")
    else:
        return HttpResponse("Your username and password didn't match.")

… А это обеспечивает выход пользователя, аналогично login() выше:

def logout(request):
    try:
        del request.session["member_id"]
    except KeyError:
        pass
    return HttpResponse("You're logged out.")

Стандартный метод django.contrib.auth.logout() в действительности выполняет гораздо больше действий для предотвращения непреднамеренной утечки данных. Он вызывает flush() объекта request.session. Мы используем этот пример в качестве демонстрации того, как можно работать с объектами сессий, а не показываем полную реализацию метода logout().

Установка проверочных кук

Для удобства Django представляет простой способ проверить принимает ли браузер пользователя куки или нет. Просто вызовите метод set_test_cookie() объекта request.session в предоставлении и затем вызовите метод test_cookie_worked() в следующем вызове представления, это важный момент.

Такое неудобное разделение set_test_cookie() и test_cookie_worked() между вызовами предоставления необходимо из-за особенностей работы механизма кук. Когда вы устанавливаете куку, вы не можете гарантировать, что браузер действительно принял куке до тех пор, пока браузер не выполнит следующий запрос.

Хорошим тоном будет использование метода delete_test_cookie() для очистки куки после проверки. Очистку следует выполнять после окончания этапа проверки наличия поддержки кук.

Покажем типичный вариант использования:

from django.http import HttpResponse
from django.shortcuts import render


def login(request):
    if request.method == "POST":
        if request.session.test_cookie_worked():
            request.session.delete_test_cookie()
            return HttpResponse("You're logged in.")
        else:
            return HttpResponse("Please enable cookies and try again.")
    request.session.set_test_cookie()
    return render(request, "foo/login_form.html")
Changed in Django 5.1:

Добавлена ​​поддержка установки тестовых файлов cookie в функциях асинхронного просмотра.

Использование сессий вне представлений

Примечание

Примеры в данном разделе импортируют объект SessionStore напрямую из хранилища django.contrib.sessions.backends.db. В своём коде вам стоит рассмотреть импортирование SessionStore из движка сессий, определенного параметром конфигурации SESSION_ENGINE, как показано ниже:

>>> from importlib import import_module
>>> from django.conf import settings
>>> SessionStore = import_module(settings.SESSION_ENGINE).SessionStore

Доступен API для управления данными сеанса вне представления:

>>> from django.contrib.sessions.backends.db import SessionStore
>>> s = SessionStore()
>>> # stored as seconds since epoch since datetimes are not serializable in JSON.
>>> s["last_login"] = 1376587691
>>> s.create()
>>> s.session_key
'2b1189a188b44ad18c35e113ac6ceead'
>>> s = SessionStore(session_key="2b1189a188b44ad18c35e113ac6ceead")
>>> s["last_login"]
1376587691

SessionStore.create() предназначен для создания нового сеанса (т.е. сеанса, не загруженного из хранилища сеансов и с session_key=None). save() предназначен для сохранения существующего сеанса (т.е. загруженного из хранилища сеансов). Вызов save() в новом сеансе также может сработать, но имеет небольшую вероятность создания session_key, который конфликтует с существующим. create() вызывает save() и выполняет цикл до тех пор, пока не будет сгенерирован неиспользуемый session_key.

Если вы используете серверную часть django.contrib.sessions.backends.db, каждый сеанс представляет собой обычную модель Django. Модель Session определена в django/contrib/sessions/models.py. Поскольку это обычная модель, вы можете получить доступ к сеансам, используя обычный API базы данных Django:

>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk="2b1189a188b44ad18c35e113ac6ceead")
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)

Обратите внимание, что вам нужно будет вызвать get_decoded(), чтобы получить словарь сеанса. Это необходимо, поскольку словарь хранится в закодированном формате:

>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}

Когда сохраняются сессии

Обычно Django выполняет сохранение в базу данных сессии только в случае внесения изменений в сессию, то есть при назначении или удалении значений словаря:

# Session is modified.
request.session["foo"] = "bar"

# Session is modified.
del request.session["foo"]

# Session is modified.
request.session["foo"] = {}

# Gotcha: Session is NOT modified, because this alters
# request.session['foo'] instead of request.session.
request.session["foo"]["bar"] = "baz"

В последнем случае вышеприведённого примера мы можем явно указать объекту сессии, что он был модифицирован, для этого надо у него установить атрибут modified:

request.session.modified = True

Для того, чтобы изменить это поведение установите параметр конфигурации SESSION_SAVE_EVERY_REQUEST в True. Это укажет Django на то, что необходимо сохранять сессию в базу данных при каждом запросе.

Следует отметить, что сессионная кука отправляется только при создании и модификации сессии. Если параметр конфигурации SESSION_SAVE_EVERY_REQUEST установлен в True, сессионная кука будет отправляться на каждый запрос.

Аналогично, значение атрибутп expires сессионной куки обновляется при каждой её отправке.

Сессия не сохраняется, если отклик имеет статус 500.

Разница между временными и постоянными куками

Вы можете указать какой должна быть длительность сессии, пока браузер не завершается или до некоторой даты, с помощью параметра конфигурации SESSION_EXPIRE_AT_BROWSER_CLOSE.

По умолчанию параметр конфигурации SESSION_EXPIRE_AT_BROWSER_CLOSE установлен в False, это означает, что сессионные куки будут храниться в браузере пользователя до тех пор, пока не истечёт время, указанное в параметре конфигурации SESSION_COOKIE_AGE. Используйте это если не желаете, чтобы пользователи авторизовались на сайте при каждом открытии браузера.

Если параметр конфигурации SESSION_EXPIRE_AT_BROWSER_CLOSE установлен в True, то Django будет использовать временные куки, такие куки работают до момента закрытия браузера. Используйте это если желаете, чтобы пользователи авторизовались на сайте при каждом открытии браузера.

Данный параметр конфигурации является глобальным, но может быть переопределён на уровне сессии с помощью явного вызова метода set_expiry() объекта request.session как было описано выше в using sessions in views.

Примечание

Некоторые браузеры (например, Chrome) предоставляют настройки, которые позволяют пользователям продолжать сеанс просмотра после закрытия и повторного открытия браузера. В некоторых случаях это может помешать настройке SESSION_EXPIRE_AT_BROWSER_CLOSE и предотвратить истечение срока действия сеансов при закрытии браузера. Помните об этом при тестировании приложений Django, в которых включен параметр SESSION_EXPIRE_AT_BROWSER_CLOSE.

Очистка хранилища сессии

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

Для понимания проблемы давайте рассмотрим, что произойдёт с хранилищем на основе базы данных. При авторизации пользователя Django добавляет запись в таблицу django_session. Django обновляет эту запись при каждом изменении данных сессии. Если пользователь завершает сеанс явно, то Django удаляет эту запись. В противном случае эта запись не удаляется. Похожее происходит и в случае файлового хранилища.

Django не обеспечивает автоматическую очистку просроченных сессий. Следовательно, эта задача ложится на вас на регулярной основе. Django представляет для этой цели команду очистки: clearsessions. Рекомендуется выполнять эту команду на регулярной основе, например, через cron ежедневно.

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

Параметры конфигурации

Несколько параметров конфигурации Django представляют вам управление поведением сессии:

Безопасность сессии

Поддомены внутри сайта имеют возможность устанавливать куки на клиенте для всего домена. Это приводит к возможности фиксации сессии, если куки принимаются от поддоменов, которые не находятся под управлением доверенных пользователей.

Например, атакующий может авторизоваться на good.example.com и получить достоверную сессию для своего аккаунта. Если у атакующего есть контроль над bad.example.com, он может использовать его для отправки своего ключа сессии вам, так как поддомену разрешено устанавливать куки для *.example.com. Когда вы посетите good.example.com, вы будете авторизован как атакующий и можете непреднамеренно внести важные персональные данные (например, номер кредитной карты) в аккаунт атакующего.

Другой возможной атакой может быть ситуация, если сайт good.example.com имеет в параметре конфигурации SESSION_COOKIE_DOMAIN значение ".example.com", что может привести отправке сессионной куки на сайт bad.example.com.

Технические детали

  • Словарь сеанса принимает любое сериализуемое значение json при использовании JSONSerializer.

  • Данные сессии сохраняются в базе данных в таблице django_session .

  • Django отправляем куки только когда это требуется. Если вы не сохранили никаких данных в сессию, то сессионная кука не будет отправляться.

Объект SessionStore

При внутренней работе с сессиями Django использует объект хранилища сессий из соответствующего механизма сессий. По соглашению класс объекта хранилища сеансов называется SessionStore и располагается в модуле, обозначенном параметром SESSION_ENGINE.

Все подклассы SessionStore, доступные в Django, реализуют следующие методы манипулирования данными:

  • существует()

  • создать()

  • сохранить()

  • удалить()

  • загрузка()

  • clear_expired()

Асинхронный интерфейс для этих методов обеспечивается путем их обертывания в sync_to_async(). Их можно реализовать напрямую, если доступна асинхронная реализация:

Чтобы создать собственный механизм сеансов или настроить существующий, вы можете создать новый класс, наследующий SessionBase или любой другой существующий класс SessionStore.

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

Changed in Django 5.1:

Были добавлены методы aexists(), acreate(), asave(), adelete(), aload() и clear_expired().

Использование базы данных для хранения сессии

Создание собственного механизма сеансов с поддержкой базы данных, построенного на основе тех, что включены в Django (а именно db и cached_db), можно выполнить путем наследования AbstractBaseSession и любого из классов``SessionStore``.

AbstractBaseSession и BaseSessionManager можно импортировать из django.contrib.sessions.base_session, поэтому их можно импортировать без включения django.contrib.sessions в INSTALLED_APPS.

class base_session.AbstractBaseSession

Абстрактная модель базового сеанса.

session_key

Первичный ключ. Само поле может содержать до 40 символов. Текущая реализация генерирует 32-символьную строку (случайную последовательность цифр и строчных букв ASCII).

session_data

Строка, содержащая закодированный и сериализованный словарь сеанса.

expire_date

Дата и время, обозначающие дату окончания сеанса.

Сеансы с истекшим сроком действия недоступны пользователю, однако они все равно могут храниться в базе данных до тех пор, пока не будет запущена команда управления clearsessions.

classmethod get_session_store_class()

Возвращает класс хранилища сеансов, который будет использоваться с этой моделью сеанса.

get_decoded()

Возвращает декодированные данные сеанса.

Декодирование выполняется классом хранилища сеансов.

Вы также можете настроить менеджер моделей, создав подкласс BaseSessionManager:

class base_session.BaseSessionManager
encode(session_dict)

Возвращает заданный словарь сеанса, сериализованный и закодированный в виде строки.

Кодирование выполняется классом хранилища сеансов, привязанным к классу модели.

save(session_key, session_dict, expire_date)

Сохраняет данные сеанса для предоставленного сеансового ключа или удаляет сеанс, если данные пусты.

Настройка классов SessionStore достигается путем переопределения методов и свойств, описанных ниже:

class backends.db.SessionStore

Использование базы данных для хранения сессии

classmethod get_model_class()

Переопределите этот метод, чтобы вернуть пользовательскую модель сеанса, если она вам нужна.

create_model_instance(data)

Возвращает новый экземпляр объекта модели сеанса, который представляет текущее состояние сеанса.

Переопределение этого метода дает возможность изменять данные модели сеанса перед их сохранением в базе данных.

class backends.cached_db.SessionStore

Использование базы данных для хранения сессии

cache_key_prefix

Префикс, добавляемый к ключу сеанса для создания строки ключа кэша.

Примеры

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

from django.contrib.sessions.backends.db import SessionStore as DBStore
from django.contrib.sessions.base_session import AbstractBaseSession
from django.db import models


class CustomSession(AbstractBaseSession):
    account_id = models.IntegerField(null=True, db_index=True)

    @classmethod
    def get_session_store_class(cls):
        return SessionStore


class SessionStore(DBStore):
    @classmethod
    def get_model_class(cls):
        return CustomSession

    def create_model_instance(self, data):
        obj = super().create_model_instance(data)
        try:
            account_id = int(data.get("_auth_user_id"))
        except (ValueError, TypeError):
            account_id = None
        obj.account_id = account_id
        return obj

Если вы переходите со встроенного в Django хранилища сеансов cached_db на собственное хранилище, основанное на cached_db, вам следует переопределить префикс ключа кэша, чтобы предотвратить конфликт пространств имен:

class SessionStore(CachedDBStore):
    cache_key_prefix = "mysessions.custom_cached_db_backend"

    # ...

Идентификаторы сессии в URL

Поддержка сессий в Django полностью, и исключительно, основана на кук. Django не помещает идентификатор сессии в URL в качестве крайнего варианта, как это делает PHP. Это - осознанное проектное решение. Мало того, что такое поведение делает URL уродливыми, оно делает ваш сайт уязвимым для воровства идентификатора сессии через заголовок «Referer».

Back to Top