4

抱歉,如果我的问题与此问题非常相似,并且我尝试解决该问题的方法是 100% 基于该问题的答案,但我认为这涉及到更多,并且可能针对我不完全理解的 Django 的一部分.


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

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

这样做的结果是每天在django_session表中创建数千个条目,并且简单地./manage clearsessions使用每日 cron 运行不会将它们从该表中删除,从而使整个数据库变得非常大而没有明显的好处。请注意,我什至尝试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 中是否有更好的方法来完成上述操作?任何建议将不胜感激。

4

2 回答 2

2

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

一种方法是包含一个中间件,根据请求丢弃会话对象。出于两个原因,这有点肮脏:

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

创建自定义中间件

class DiscardSessionForAPIMiddleware(object):

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

确保. _ django.contrib.sessions.middleware.SessionMiddleware_ MIDDLEWARE_CLASSES_settings.py

还要检查settings.SESSION_SAVE_EVERY_REQUEST设置为False(默认值)。这使得它延迟写入数据库,直到数据被修改。


替代品(未经测试)

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

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

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

于 2013-06-13T13:32:13.397 回答