Я пошел по пути «Адаптируйте промежуточное программное обеспечение», так как похоже, что сеанс создается только при доступе к сеансу или - в случае совершенно новых сеансов - во время обработки ответа в SessionMiddleware.
Итак, я создал это Middleware, расширяющее SessionMiddleware
:
from django.contrib.sessions.middleware import SessionMiddleware
from django.http import HttpRequest
class ConditionalSessionMiddleware(SessionMiddleware):
def process_request(self, request: HttpRequest):
# Default: We need a Session
setattr(request, '_conditional_session_middleware_session_required', True)
return super(ConditionalSessionMiddleware, self).process_request(request)
def process_response(self, request: HttpRequest, response):
# Is still a Session required?
required = getattr(request, '_conditional_session_middleware_session_required', True)
# or is the user not anonymous?
if required or not request.user.is_anonymous:
return super(ConditionalSessionMiddleware, self).process_response(request, response)
else:
return response
Чтобы использовать его, я создал простой декоратор функций:
from types import MethodType
class NoSessionUsed:
def __init__(self, f):
self.__func = f
def __call__(self, *args, **kwargs):
for a in args:
if isinstance(a, HttpRequest):
setattr(a, '_conditional_session_middleware_session_required', False)
break
return self.__func(*args, **kwargs)
def __get__(self, instance, owner):
if instance:
return MethodType(self, instance)
else:
return self
В основанном на классе Представления, я использую декоратор по методу dispatch
:
@NoSessionUsed
def dispatch(self, request, *args, **kwargs):
return super(MyClassBasedView, self).dispatch(request, *args, **kwargs)
Вы также можете использовать его в urls.py, например, для файлов Sitemap и каналов, где у вас нет прямого доступа к представлениям:
urlpatterns = [
path('rss.xml', NoSessionUsed(RssFeed()), name='rss'),
path('atom.xml', NoSessionUsed(AtomFeed()), name='atom'),
path('sitemap.xml', NoSessionUsed(views.index), {
'sitemaps': SITEMAPS,
'sitemap_url_name': 'sitemaps:sitemap.section'
}, name='sitemap'),
path('sitemaps/sitemap-<section>.xml', NoSessionUsed(views.sitemap), {
'sitemaps': SITEMAPS
}, name='sitemap.section'),
]
Чтобы активировать новое Middleware, я заменил SessionMiddleware
в разделе settings.py MIDDLEWARE
на новый ConditionalSessionMiddleware
.
Конечно, есть и недостатки:
- Когда я использую сеансы в декорированном виде, изменения, скорее всего, не будут сохранены
- Когда я использую новые сеансы в декорированном виде, пользователь не получит Повар сеанса ie
Возможно, это не идеальное решение, но это довольно просто и работает для меня.