5

I would like to use Custom Django Middleware (Django 1.9) to check whether or not an anonymous user has accepted a site's terms & conditions - I'll show the user a dialog if they've not yet clicked 'Agree'.

I have no need to store this in the database and would prefer to simply use a Cookie. I have the following in 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'

I'm then trying something very rudimentary in TermsMiddleware - here I'm deliberately trying to modify the request and the response just to try to get it to work:

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

If I inspect the response in the browser, I see that myCookieKey isn't being set, so I think I've misunderstood how this should be written.

Can I manipulate the session within middleware like this, having it take effect in the cookie sent in the response Django was going to send anyway? The documentation makes it sound like I should be able to:

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.

I've also seen the note in the documentation to use SessionStore() when outside of a view function. In theory I don't think I should need to do that here because I've got access to request (and response). I tried it anyway, and I still couldn't get it to work.

Help much appreciated!

Paul J
  • 799
  • 1
  • 6
  • 16

1 Answers1

4

The thing you've misunderstood is the relationship between the session and the cookies.

You can't set arbitrary cookies by modifying the session. The session is a collection of data, usually stored in the db or a file, and the only cookie is the one that contains the session key for the current user.

You certainly can modify the session in middleware, but wherever you do so, you shouldn't expect to see a cookie being set.

(Separately, you should never call double underscore methods like __setitem__ directly. The session is accessed via a dict-like interface: request.session['foo'] = 'bar'.)

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Thanks for the reply Daniel - if this is the case, what does the documentation mean by "Cookies contain a session ID – not the data itself (unless you’re using the cookie based backend).". The latter part of that makes it seem like I should indeed see the data itself in the cookie (since I am using the cookie based backend)? And yes, agree on using the dict interface - I'll edit the code above. – Paul J Feb 04 '17 at 23:33
  • 1
    But it's still the session cookie, not a specific one for each value. And in that cookie, the session data is stored in an encoded form; you won't see keys and values. – Daniel Roseman Feb 04 '17 at 23:54