by crodjer on December 24, 2010, tagged django, web

The first thing the title triggers in the mind is the django sites framework. Well this post is mostly related to that but suggests its utilization in slight different way. As we can get from the docs in every implementation of the sites framework you have to hardcode the SITE_ID in your settings.py file. So it assumes that you have multiple django projects or at least multiple settings.py files which will be used as the django settings module for the process. So basically it provides us to share database between multiple sites which is a nice feature.

For our case which is, we want to use a single django project to across multiple domains while presenting altered versions of content dependant on the originating domain (the domain names cannot be hardcoded as the number of domains is dynamic too.), we have to do something different to get this level of dynamicity. I did sone research about this on the #django IRC, stackoverflow and google. Here are some complete/incomplete ways I found out to achieve this.

Using custom apps and modules

These ways would need us to define many custom models and middleware, hence a lot of work. The domain management would be done by the django project itself through middleware which use the HTTP_REQUST header and hence every request will be processed to obtain the information required to do database queries and render the views. So these methods looks like bit safer but would cause a performance decrease.

Modify contrib

This is the rather easier way which involves modifications of code of some django contrib apps here and there. Just copy the apps from django->contrib folder to the project directory and modify them to accept request as argument give out results according to the HTTP_HOST and Sites database. Also change all the imo reference of these apps from django.contrib.app to app.

Forget contrib

Another way would be to forget the contrib apps and write your own custom similar ones from scratch. This may be a better way for long term projects which require highly customized and special functionalities. But it will require us to write a lot of code, though the existing modules can be used for reference.

Using unaltered django modules

If we are successful in doing this it will probably let us build our project in much less lines of code and using the already existent django contribs as is. So if we don’t modify django modules then what do we modify to achieve the dynamicity.

wsgi

This is what we could do: First define multiple settings files in some pattern so that they can be matched according to the domain name, say settings_domain.py. Now if the deployment is done using wsgi script (generally in this) format. In the wsgi script we have to call the respective settings_domain.py according to the accessing domain name. So this seems pretty good but it can be dangerous. As we are setting a global variable (os.environ['DJANGO_SETTINGS_MODULE']) it is not at all a thread safe method. If there are two requests close enough this may pose dangerous effects. Unless we are not able to make sure that a new fork / new wsgi demon will be created per domain. So maybe one could suggest to write a good wsgi script which could handle this.

htaccess

Yet another way would be to make the .htaccess file dynamic, if it is possible. I don’t have any idea if I could write an apache config file that would trigger the correct wsgi file (which triggers the correct settings one). Maybe one could suggest a way of doing this (through regex?). To me thiss seems the best way which would trigger a corresponding process for each domain.

django-multisite

This is a django application I found (Source: https://github.com/shestera/django-multisite) which utilize thread locals to dynamically define the SITE_ID setting according to the request domain. I have tried this and is actually working but as the django documentation has pretty clearly warned against its use, I am in doubt if it is a safe way.

Till now I am still unclear of what method to implement among the above or some other one. There are some pros and cons of all the methods.

I apologise if I have written something wrong, these all are only some methods I have found out while searching the web and discussing on the groups, so please specify if there is any mistake or you can suggest something related to this.

Fork me on GitHub