Django:如何从会话创建中排除视图?

Django:如何从会话创建中排除视图?,django,django-views,django-sessions,Django,Django Views,Django Sessions,我的Django项目严重依赖于会话,框架在这方面做得非常好。它主要通过SessionMiddleware管理会话cookie、会话数据库等 但是有一些视图明确地不需要会话。这些视图通常显示为页面的一个条目 我可以从创建新会话的SessionMiddleware中排除这些视图吗?如果新(匿名)用户访问此类视图并离开,则无需在会话表中设置Cookie或创建数据库记录。我采用了“调整中间件”的方式,因为看起来只有在访问会话时才创建会话,或者在SessionMiddleware中处理响应时(如果是全新的

我的Django项目严重依赖于会话,框架在这方面做得非常好。它主要通过SessionMiddleware管理会话cookie、会话数据库等

但是有一些视图明确地不需要会话。这些视图通常显示为页面的一个条目

我可以从创建新会话的SessionMiddleware中排除这些视图吗?如果新(匿名)用户访问此类视图并离开,则无需在会话表中设置Cookie或创建数据库记录。

我采用了“调整中间件”的方式,因为看起来只有在访问会话时才创建会话,或者在SessionMiddleware中处理响应时(如果是全新的会话)

所以我创建了这个中间件,它扩展了
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
方法上使用decorator:

@NoSessionUsed
def dispatch(self, request, *args, **kwargs):
    return super(MyClassBasedView, self).dispatch(request, *args, **kwargs)
您也可以在URL.py中使用它,例如,对于无法直接访问视图的站点地图和提要:

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'),
]
urlpatterns=[
path('rss.xml',NoSessionUsed(RssFeed()),name='rss'),
path('atom.xml',NoSessionUsed(AtomFeed()),name='atom'),
使用的路径('sitemap.xml')(views.index){
“站点地图”:站点地图,
“站点地图url\u名称”:“站点地图:站点地图.section”
},name='sitemap'),
路径('sitemaps/sitemap-.xml',已使用(views.sitemap){
“站点地图”:站点地图
},name='sitemap.section'),
]
为了激活新的中间件,我将settings.py
Middleware
部分中的
SessionMiddleware
替换为新的
ConditionalSessionMiddleware

当然也有不利因素:

  • 在装饰视图中使用会话时,更改很可能不会保存
  • 当我在装饰视图中使用新会话时,用户将不会获得会话Cookie
这可能不是一个完美的解决方案,但它非常简单,对我来说很有效。

我采用了“调整中间件”的方式,因为它看起来像是只在访问会话时创建会话,或者在处理会话中间件中的响应时(如果是全新的会话)

所以我创建了这个中间件,它扩展了
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
方法上使用decorator:

@NoSessionUsed
def dispatch(self, request, *args, **kwargs):
    return super(MyClassBasedView, self).dispatch(request, *args, **kwargs)
您也可以在URL.py中使用它,例如,对于无法直接访问视图的站点地图和提要:

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'),
]
urlpatterns=[
path('rss.xml',NoSessionUsed(RssFeed()),name='rss'),
path('atom.xml',NoSessionUsed(AtomFeed()),name='atom'),
使用的路径('sitemap.xml')(views.index){
“站点地图”:站点地图,
“站点地图url\u名称”:“站点地图:站点地图.section”
},name='sitemap'),
路径('sitemaps/sitemap-.xml',已使用(views.sitemap){
“站点地图”:站点地图
},name='sitemap.section'),
]
为了激活新的中间件,我将settings.py
Middleware
部分中的
SessionMiddleware
替换为新的
ConditionalSessionMiddleware

当然也有不利因素:

  • 在装饰视图中使用会话时,更改很可能不会保存
  • 当我在装饰视图中使用新会话时,用户将不会获得会话Cookie

这可能不是一个完美的解决方案,但它非常简单,对我来说很有效。

访问此类视图的用户是经过身份验证的用户还是匿名用户?@AKS:会话只会为匿名用户创建。一个经过身份验证的用户已经有了一个会话,所以我不在乎是否由于视图的访问而设置了cookie。但是对于匿名用户,我不希望有新会话。您可以扩展
SessionMiddleware
并覆盖
process\u请求
process\u响应
,以匹配您的用例。在这里,您可以比较视图名称并提前返回,而无需进行处理。然后在“设置”中,用您自己的会话中间件替换会话中间件。@AKS:已经想到了,但希望有一种更简单的、配置或注释驱动的方法。我不确定是否有这种方法查看源代码。因此,如果您想更改该行为,我认为您必须扩展该类。访问此类视图的用户是经过身份验证的用户还是匿名用户?@AKS:将仅为匿名用户创建会话。一个经过身份验证的用户已经有了一个会话,所以我不在乎是否由于视图的访问而设置了cookie。但是对于匿名用户,我不希望有新会话。您可以扩展
SessionMiddleware
并覆盖
process\u请求
process\u响应
,以匹配您的用例。在这里,您可以比较视图名称并提前返回,而无需进行处理。然后在“设置”中,用您自己的会话中间件替换会话中间件。@AKS:已经想到了,但希望有一种更简单的、配置或注释驱动的方法。我不确定是否有这种方法查看源代码。所以如果你想改变行为,我认为你必须扩展这个类。