在 Django 中间件中设置 cookie

Setting cookies within Django Middleware

我想使用自定义 Django 中间件 (Django 1.9) 检查匿名用户是否已接受网站的条款和条件 - 如果用户尚未单击,我将显示一个对话框 'Agree'.

我不需要将其存储在数据库中,而更愿意简单地使用 Cookie。我在 settings.py 中有以下内容:

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    ...
    'myapp.middleware.app_custom_middleware.TermsMiddleware',]

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'

然后我在 TermsMiddleware 中尝试一些非常基本的东西 - 在这里我故意尝试修改请求 响应只是为了让它工作:

class TermsMiddleware(object):

    def process_request(self, request):
        request.session['myCookieKey'] = 'myCookieValue'
        request.session.save()
        return

    def process_response(self, request, response):
        request.session['myCookieKey'] = 'myCookieValue'
        request.session.save()
        return response

如果我检查浏览器中的响应,我发现 myCookieKey 没有被设置,所以我想我误解了应该如何写。

我可以像这样在中间件中操作会话,让它在 Django 无论如何都会发送的响应中发送的 cookie 中生效吗?文档听起来我应该能够:

It should return either None or an HttpResponse object. If it returns None, Django will continue processing this request, executing any other process_request() middleware, then, process_view() middleware, and finally, the appropriate view. If it returns an HttpResponse object, Django won’t bother calling any other request, view or exception middleware, or the appropriate view; it’ll apply response middleware to that HttpResponse, and return the result.

我还在文档中看到了在视图函数外部使用 SessionStore() 的说明。理论上我认为我不需要在这里这样做,因为我可以访问 request(和 response)。反正我试过了,还是不行。

非常感谢帮助!

你误解了会话和 cookie 之间的关系。

您不能通过修改会话来设置任意cookie。 session是一组数据,通常存储在db或文件中,唯一的cookie是包含当前用户session key的cookie。

您当然可以在中间件中修改会话,但无论您这样做,都不应期望看到正在设置的 cookie。

(另外,你不应该直接调用像 __setitem__ 这样的双下划线方法。会话是通过 dict-like 接口访问的:request.session['foo'] = 'bar'。)