How to prevent Django from writing to the django_session table for specific URLs

I apologize if my question is very similar to this one , and my approach to solving the problem is 100% based on the answers to this question, but I think it is a little more involved and can target the part of Django that I do not quite understand.


I have a CMS system written in Django 1.5, with several APIs available by two desktop applications that cannot use cookies as a browser.

I noticed that every time an API call is made by one of the applications (once every 3 seconds), a new record is added to the django_session table. By carefully studying this table and code, I see that for all entries for a particular URL, the same session_data value is set, but a different session_key . This is probably due to the fact that Django determines that when one of these calls is made from an application without cookies, request.session._session_key is set to None .

The result of this is that thousands of records are created every day in the django_session table and just running ./manage clearsessions , using a daily cron, does not delete them from this table, making the entire database quite large, without obvious benefit. Note that I even tried set_expiry(1) for these queries, but ./manage clearsessions still doesn't get rid of them.

To overcome this problem with Django, I had to override 3 Django middlewares since I use SessionMiddleware, AuthenticationMiddleware and 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 

Although the above works, I can’t stop thinking that I may have made it more complicated, that it really is, and that this is not the most efficient approach, since 4 additional checks have been done for each individual request.

Are there any better ways to do this in Django? Any suggestions would be greatly appreciated.

+4
source share
2 answers

Dirty hack: conditionally delete a session object.

One approach will include one middleware that discards the session object due to the request. This is a slightly dirty hack for two reasons:

  • The Session object is created first and deleted later. (Inefficient)
  • You rely on the fact that the Session object is not yet written to the database. This may change in future versions of Django (although not very likely).

Create custom middleware :

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

Make sure you install this after django.contrib.sessions.middleware.SessionMiddleware in the MIDDLEWARE_CLASSES tuple in settings.py .

Also check that settings.SESSION_SAVE_EVERY_REQUEST set to False (default). This causes it to delay writing to the database until the data is modified.


Alternatives (untested)

  • Use process_view instead of process_request in your custom middleware so you can check the view instead of the request path. Advantage: checking the condition is better. Disadvantage: other middleware may already do something with the session object, and then this approach does not work.
  • Create your own decorator (or common base class) for your API views by deleting the session object there. Advantage: The responsibility for this will depend on the views, the places where you probably like it best (viewing the API). Disadvantage: the same as above, but deleting the session object at an even later stage.
+2
source

Make sure settings.SESSION_SAVE_EVERY_REQUEST set to False . This is a long way to ensure that sessions are not saved every time.

Also, if you have any ajax requests going to your server, make sure the request contains cookie information so that the server does not think that each request belongs to a different person.

0
source

Source: https://habr.com/ru/post/1486004/


All Articles