﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33533	Should it be impossible for a session dict to return more than one value for a key?	Michael	nobody	"In my project, there are some methods on a custom user model that require the `request` to calculate certain values. This simple middleware does the trick:

{{{
class AttachRequestToUserMiddleware:
    """"""Adds the request to the user object, so session information can be looked
    up by the custom user model.

    Must come after django.contrib.auth.middleware.AuthenticationMiddleware which adds the user""""""

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        request.user.request = request
        return self.get_response(request)
}}}

In production, when there are multiple workers running parrallel by uWSGI, if one has `SESSION_SAVE_EVERY_REQUEST = True`, then if one makes async requests from JavaScript (e.g. say a Service Worker caching pages on install), then the way it saves/retrieves sessions on every request fails in many spectacular ways.

Here are some example trace backs:
{{{
Django Version:	4.0.1
Python Version:	3.8.5

Exception Type:	ProgrammingError
Exception Value:	
no results to fetch
Exception Location:	/home/michael/.venv/project/lib/python3.8/site-packages/django/db/utils.py, line 97, in inner
/home/michael/.venv/project/lib/python3.8/site-packages/django/db/utils.py, line 97, in inner
                return func(*args, **kwargs)


Exception Type:	RuntimeError
Exception Value:	
generator raised StopIteration
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/auth/__init__.py, line 60, in _get_user_session_key
return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])

Exception Type:	MultipleObjectsReturned
Exception Value:	
get() returned more than one Session -- it returned 2!
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/sessions/backends/base.py, line 180, in _get_session
            return self._session_cache
/home/michael/.venv/project/lib/python3.8/site-packages/django/core/handlers/exception.py, line 47, in inner
                response = get_response(request)
./core/accounts/middleware.py, line 33, in __call__
        request.user.request = request
/home/michael/.venv/project/lib/python3.8/site-packages/django/utils/functional.py, line 278, in __setattr__
                self._setup()
/home/michael/.venv/project/lib/python3.8/site-packages/django/utils/functional.py, line 384, in _setup
        self._wrapped = self._setupfunc()
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/auth/middleware.py, line 25, in <lambda>
        request.user = SimpleLazyObject(lambda: get_user(request))
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/auth/middleware.py, line 11, in get_user
        request._cached_user = auth.get_user(request)
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/auth/__init__.py, line 177, in get_user
        user_id = _get_user_session_key(request)
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/auth/__init__.py, line 60, in _get_user_session_key
    return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/sessions/backends/base.py, line 50, in __getitem__
        return self._session[key]
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/sessions/backends/base.py, line 185, in _get_session
                self._session_cache = self.load()
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/sessions/backends/db.py, line 43, in load
        s = self._get_session_from_db()
/home/michael/.venv/project/lib/python3.8/site-packages/django/contrib/sessions/backends/db.py, line 32, in _get_session_from_db
            return self.model.objects.get(
/home/michael/.venv/project/lib/python3.8/site-packages/django/db/models/manager.py, line 85, in manager_method
                return getattr(self.get_queryset(), name)(*args, **kwargs)
/home/michael/.venv/project/lib/python3.8/site-packages/django/db/models/query.py, line 443, in get
        raise self.model.MultipleObjectsReturned(
}}}
"	Uncategorized	closed	contrib.sessions	4.0	Normal	invalid			Unreviewed	0	0	0	0	0	0
