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

#django #session #django-sessions

#django #сеанс #django-сеансы

Вопрос:

Я пытаюсь понять, как работает сеанс в Django. Просматривая исходный код SessionMiddleware :

 class SessionMiddleware(object): 
    def process_request(self, request): 
        engine = import_module(settings.SESSION_ENGINE) 
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None) 
        request.session = engine.SessionStore(session_key) 
  

Если я правильно понимаю, для каждого запроса
SessionMiddleware.process_request() получит sessionid из
cookie, а затем создайте новый SessionStore экземпляр, используя это
sessionid .

И когда я посмотрел на источник для __init__() of SessionStore и SessionBase :

   class SessionStore(SessionBase): 
      def __init__(self, session_key=None): 
          super(SessionStore, self).__init__(session_key) 

  class SessionBase(object): 
      def __init__(self, session_key=None): 
          self._session_key = session_key 
          self.accessed = False 
          self.modified = False 
  

Таким образом, в основном SessionStore просто создает новый экземпляр, не пытаясь
чтобы посмотреть в базе данных, существует ли уже сеанс с указанным sessionid
или нет. Но разве не в этом должен быть весь смысл сеанса — в том, что для каждого
запрос Django необходимо просмотреть в базе данных сеанса, чтобы увидеть, существует ли
сеанс уже существует? Я предполагаю, что в каком-то месте этот поиск по базе данных
происходит, но я не могу его найти.

Не могли бы вы сказать мне, где я могу это найти? Или я неправильно понял, как работает сеанс в Django?

Спасибо

Ответ №1:

Третья строка SessionMiddleware вызывает определенный механизм сеансов, который определяет, какой SessionStore использовать.

Если вы перейдете в contrib/sessions/backends/base.py вы увидите следующий код:

 class SessionBase(object):

    ...

    def __getitem__(self, key):
        return self._session[key]

    def _get_session(self, no_load=False):
        """
        Lazily loads session from storage (unless "no_load" is True, when only
        an empty dict is stored) and stores it in the current instance.
        """
        self.accessed = True
        try:
            return self._session_cache
        except AttributeError:
            if self._session_key is None or no_load:
                self._session_cache = {}
            else:
                self._session_cache = self.load()
        return self._session_cache

    _session = property(_get_session)
  

Что это делает, так это создает объект session proxy, который промежуточное программное обеспечение прикрепило к запросу. Он не загружает объект сеанса из базы данных, пока вы не скажете:

 x = request.session['key']
  

В этот момент программа __getitem__(self, key) пытается выполнить разыменование self._session , которое (будучи свойством), в свою очередь, возвращает кэшированную копию словаря сеанса для этой транзакции, или, если кэш недоступен, извлекает его из хранилища с помощью load() метода. load() Метод реализуется конкретными дочерними движками: database, file, cache, cache db и т.д.

SessionStore это облегченный прокси-сервер для полного сеанса; он становится полным сеансом, попадая в базу данных, только когда вам нужно прочитать или записать данные в объект сеанса, связанный с ключом, закодированным в cookie идентификатора сеанса.