Сегодняшняя тема для обсуждения — вызывает ли request.session.get() в Django снижение производительности? 🎯

При разработке на Django мы часто вызываем request.session.get('key_name'), верно? Но меня осенило:

"Поскольку сессии в конечном итоге хранятся в БД, происходит ли запрос к БД каждый раз, когда мы вызываем request.session.get()?"

"Или Django каким-то образом умело обрабатывает это так, что дополнительных запросов не возникает?"

Чтобы прояснить этот вопрос, я углубился в исходный код SessionMiddleware Django и провел эксперимент. 🚀

1️⃣ Как Django создает request.session?

Давайте разберемся, когда Django загружает сессии, когда создает объект запроса.

Процесс управления сессиями в Django

Обычно мы получаем данные сессии в функции представления следующим образом.

session_username = request.session.get('username')

Но если request.session.get('username') вызывает запрос к БД каждый раз, это может существенно повлиять на производительность, верно?

🔍 Давайте взглянем на внутренности Django!

На самом деле, Django загружает данные сессий заранее через промежуточное программное обеспечение, называемое SessionMiddleware, когда поступает запрос. На этом этапе происходит только один запрос к БД, а затем данные сессии остаются в объекте request.

В коде SessionMiddleware Django наблюдается следующее:

class SessionMiddleware(MiddlewareMixin):
    def process_request(self, request):
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
        request.session = self.SessionStore(session_key)

📌 Важно запомнить!

  • ✅ Мы получаем ключ сессии (session_key) из request.COOKIES.
  • ✅ Вызывая self.SessionStore(session_key), мы загружаем данные сессии один раз из БД и сохраняем их в request.session.
  • ✅ Таким образом, даже если мы многократно вызываем request.session.get() в функции представления, дополнительных запросов к БД не происходит! 🎯

2️⃣ Вызывает ли request.session.get() запросы к БД?

Вернемся к главному вопросу.

"Вызывает ли запрос к БД вызов request.session.get('username') в представлении?"

🚀 Если сказать кратко, вызов request.session.get() не приводит к дополнительным запросам к БД.

Причина проста.
✔ Django один раз загружает данные сессий при поступлении запроса и сохраняет их в request.session.
✔ Следующие вызовы request.session.get() просто извлекают данные, уже загруженные в память, и дополнительные запросы к БД не нужны.

На самом деле запросы к БД происходят только один раз в начале запроса. SQL-запросы, которые исполняются в этот момент, выглядят так:

SELECT session_data FROM django_session WHERE session_key = 'xyz123' LIMIT 1;

 Таким образом, ✅ даже если мы многократно вызываем request.session.get() в представлении, Django не выполняет дополнительных запросов к БД!
      ✅ Запрос к БД выполняется только один раз, когда данные загружаются при первом запросе!

3️⃣ Возникают ли запросы при использовании данных сессии в шаблонах?

"Если мы передаем данные сессии из представления в шаблон, и затем используем их там, возникают ли дополнительные запросы к БД?"

Предположим, что мы передаем данные сессии в представление следующим образом:

def my_view(request):
    session_username = request.session.get('username')  # Запрос к БД? ❌
    return render(request, 'my_template.html', {'session_username': session_username})

А затем используем их в шаблоне:

<p>Вход как: {{ session_username }}</p>

В этом случае также не возникает дополнительных запросов к БД!

session_username — это значение, уже полученное из request.session, поэтому при передаче в шаблон никаких дополнительных запросов к БД не требуется.

✔ Django управляет request.session как кэш в памяти, поэтому его можно безопасно использовать в шаблонах.


4️⃣ Если изменить данные сессии, будут ли они сохранены в БД?

"А если я изменю данные, например так: request.session['username'] = 'new_value'?"

🚀 В этом случае изменения будут сохранены в БД, и произойдет дополнительный запрос к БД!

Если, например, мы изменим данные сессии так:

request.session['username'] = 'new_value'

Django сохранит измененные данные сессии в БД при отправке ответа. SQL-запрос, который будет выполнен, выглядит следующим образом:

UPDATE django_session SET session_data = 'new_value' WHERE session_key = 'xyz123';

Чтение сессии не вызывает запросов к БД, но изменение сессии приводит к выполнению запросов для сохранения в БД.


5️⃣ Различия в способах хранения сессий (бэкенда)

Дjango позволяет изменять способ хранения сессий (бэкенд). Необходимо учитывать, что в зависимости от бэкенда могут различаться запросы.

Бэкенд сессий Описание Запросы к БД
django.contrib.sessions.backends.db Сессии на основе БД по умолчанию ✅ Один раз при запросе
django.contrib.sessions.backends.cache Сессии, основанные на кэше (Redis, Memcached) ❌ Без запросов к БД
django.contrib.sessions.backends.cached_db Кэш + БД сессии (если нет кэша, то запрос к БД) 🚀 Запрос, если нет в кэше
django.contrib.sessions.backends.signed_cookies Сессии на основе cookies ❌ Без запросов к БД

🚀 Таким образом, использованием cache или signed_cookies бэкендов позволяет работать с сессиями без запросов к БД. ✔ В случаях, когда производительность критична, рассмотрение CACHED_DB_SESSION может быть отличным вариантом.


🎯 Заключение

  • ✅ Django загружает данные сессий заранее через SessionMiddleware, сохраняя их в request.session.
  • ✅ Следовательно, вызов request.session.get('username') в представлении не приводит к дополнительным запросам к БД.
  • Во время использования данных сессий в шаблонах тоже не возникают дополнительные запросы к БД.
  • ✅ Однако, если изменить значение сессии, Django сохранит измененное значение в БД, когда отправляет ответ.
  • ✅ В соответствии с настройками бэкенда сессий возникновение запросов может различаться, использование кэшированных (например, cache или cached_db) вариантов помогает уменьшить нагрузку на БД.

🔥 Анонс следующего выпуска: когда исчезает объект request?

Итак, когда исчезает объект request?

  • Продолжает ли он занимать память даже после завершения запроса?

  • Очищается ли автоматически системой или нам нужно убирать его самостоятельно?

🚀 В следующем выпуске мы исследуем жизненный цикл объекта request в Django и управление памятью! Ожидайте с нетерпением! 😃