divio/django-cms — pull request #3234 by damianmoore (2014-06-08 15:54:28+00:00)
Title: Prevent interference between sites when using multi-host/dynamic site setups

I've spent a log time trying to get several sites hosted under a single Django instance. Django doesn't yet provide what I would consider a nice way to do this but there are many tutorials, applications and snippets available. They generally get the hostname from the `request`, use that to lookup a `Site` object in the database and change the `SITE_ID` based upon it. These are a few examples:

https://pypi.python.org/pypi/django-threaded-multihost
http://blog.uysrc.com/2011/03/23/serving-multiple-sites-with-django/
https://bitbucket.org/uysrc/django-dynamicsites/
https://pypi.python.org/pypi/django-multihost
http://sandbox.effbot.org/zone/django-multihost.htm
https://djangosnippets.org/snippets/1509/

Whist I know you will think that changing a `settings` attribute on the fly is nasty, Django doesn't offer any better way. Many people are apparently using Django in this way in production and the top link in my list has over 18000 PyPI downloads in the last month.

My multi-host setup was working fine locally under `runserver` but when I came to deploy the first time I visited the various sites and would see other previously visited sites under the same Django project. This was made even more confusing when running multiple workers as repeatedly refreshing on single site would randomly show other sites.

I went through the process of trialling various different implementations (linked to above) and writing my own, assuming that there must be a problem with the Django middleware not setting SITE_ID correctly due to some sort of threading issues. It was only once I removed Django-CMS from my project and used some urls/views of my own that I found out the various multi-site middleware implementations had been working all along. I then started digging into Django-CMS code and found the page cache key that was not including the current site.

Sorry for the length of this comment but it has been mind-numbing looking in the wrong place all along and I expect there to be others stuck at the same hurdle. I have my own fork but I wouldn't want anyone else to spend more time than they have to on this for the sake of a few extra characters in this cache key.

As an aside, I am a contractor at an agency and I know the sysadmins there would like to move to multi-site Django-CMS-based configuration like this. They have Django-CMS projects which each contain tens of sub sites so just having a single pool of workers will drastically increase availability, reduce complexity and probably reduce memory.