Django: Как исключить представление из создания сеанса? - PullRequest
1 голос
/ 14 марта 2020

Мой Django Проект сильно зависит от сессий, и Framework отлично справляется с этим. Он управляет сессионными cookie-файлами, базой данных сессий и т. Д., В основном через SessionMiddleware.

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

Можно ли исключить эти представления из SessionMiddleware при создании новых сеансов? Если новый (анонимный) пользователь посещает такое представление и уходит, нет необходимости устанавливать Cook ie или создавать запись базы данных в таблице сеансов.

1 Ответ

0 голосов
/ 14 марта 2020

Я пошел по пути «Адаптируйте промежуточное программное обеспечение», так как похоже, что сеанс создается только при доступе к сеансу или - в случае совершенно новых сеансов - во время обработки ответа в 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

Возможно, это не идеальное решение, но это довольно просто и работает для меня.

...