如何防止Django为某些URL写入django_session表

时间:2013-06-13 12:18:02

标签: django session django-sessions

道歉,如果我的问题与this one非常相似,我试图解决问题的方法是100%基于该问题的答案,但我认为这稍微涉及更多,可能针对Django的一部分我完全不明白。


我有一个用Django 1.5编写的CMS系统,其中有一些API可供两个桌面应用程序访问,这些应用程序无法像浏览器那样使用cookie。

我注意到,每当其中一个应用程序(每3秒一次)进行API调用时,就会在django_session表中添加一个新条目。仔细查看此表和代码,我可以看到特定网址的所有条目都被赋予相同的session_data值但不同的session_key。这可能是因为Django确定当其中一个调用来自无cookie应用程序时,request.session._session_keyNone

这样做的结果是每天在django_session表中创建了数千个条目,只使用每日cron运行./manage clearsessions将不会从这个表中删除它们,使整个数据库非常大而不是明显的好处。请注意,我甚至尝试set_expiry(1)来处理这些请求,但./manage clearsessions仍然没有删除它们。

为了通过Django克服这个问题,我不得不重写3个Django中间件,因为我正在使用SessionMiddleware,AuthenticationMiddleware和MessageMiddleware:

from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.auth.middleware import AuthenticationMiddleware
from django.contrib.messages.middleware import MessageMiddleware

class MySessionMiddleware(SessionMiddleware):
    def process_request(self, request):
        if ignore_these_requests(request):
            return
        super(MySessionMiddleware, self).process_request(request)

    def process_response(self, request, response):
        if ignore_these_requests(request):
            return response
        return super(MySessionMiddleware, self).process_response(request, response)

class MyAuthenticationMiddleware(AuthenticationMiddleware):
    def process_request(self, request):
        if ignore_these_requests(request):
            return
        super(MyAuthenticationMiddleware, self).process_request(request)

class MyMessageMiddleware(MessageMiddleware):
    def process_request(self, request):
        if ignore_these_requests(request):
            return
        super(MyMessageMiddleware, self).process_request(request)

def ignore_these_requests(request):
    if request.POST and request.path.startswith('/api/url1/'):
            return True
    elif request.path.startswith('/api/url2/'):
        return True
    return False

虽然上述方法有效,但我不能不认为我可能会让它变得更加复杂,而且这不是最有效的方法,因为每次请求都会进行4次额外检查。

有没有更好的方法在Django中执行上述操作?任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:2)

Dirty hack:有条件地删除会话对象。

一种方法是包括一个中间件,以请求为条件丢弃会话对象。这有点肮脏,有两个原因:

  • 首先创建Session对象,稍后删除。 (低效)
  • 您依赖于此时Session对象尚未写入数据库的事实。这可能会在未来的Django版本中发生变化(尽管不太可能)。

创建custom middleware

class DiscardSessionForAPIMiddleware(object):

    def process_request(self, request):
        if request.path.startswith("/api/"): # Or any other condition
            del request.session

确保在<{1}}中的django.contrib.sessions.middleware.SessionMiddleware元组中 {/ 1}}后安装此

同时检查settings.SESSION_SAVE_EVERY_REQUEST是否设置为MIDDLEWARE_CLASSES(默认值)。这使得它延迟了对数据库的写入,直到数据被修改。


替代品(未经测试)

  • 在自定义中间件中使用settings.py代替False,以便您可以检查视图而不是请求路径。优点:条件检查更好。缺点:其他中间件可能已经对会话对象做了一些事情,然后这种方法失败了。
  • 为您的API视图创建自定义装饰器(或共享基类),删除其中的会话对象。优势:这样做的责任在于视图,您最喜欢的地方(查看提供API)。缺点:与上述相同,但在更晚的阶段删除会话对象。

答案 1 :(得分:0)

确保settings.SESSION_SAVE_EVERY_REQUEST设置为False。这将大大有助于确保每次都不会保存会话。

此外,如果您有任何ajax请求发送到您的服务器,请确保该请求包含cookie信息,以便服务器不会认为每个请求都属于另一个人。