Multiple Domain Hosting With One Django Project
Question: I'm new to Django and python in general, so please bear with me. I want to
create a very simple SaaS app to get started with Django and python. My design
dictates that all domains will run on the same codebase. The only thing that
will differ between each website is the database connection details. (IE each
domain receives its own database. All databases contain the same schema)

How would I go about this with Django? I've seen the Sites framework, but I'm
not sure that's what I'm looking for. Essentially, I'd like to either

A) Have Django look up the database connection details from a MASTER database,
when the page loads, and then use those details when connecting to the site
database

B) Have a settings.py per-site and have django include the correct file at
runtime (IE settings_domain.py)

C) Have the index WSGI include the appropriate settings file based on the
accessing domain (This seems like it could work, but I'm sure I'm missing a
potential pitfall of this implementation)

D) Some other implementation I haven't thought of....

Am I making this more complicated than it needs to be? How can I easily
implement this functionality into a new django project?


Answer: Well, there's an interesting project at: <https://bitbucket.org/uysrc/django-
dynamicsites>. It attempts to let you have entirely unique sites all running
off the same project. However, currently, I don't think it will do much for
you since you're going to need a bit more customization over settings than it
offers.

I actually just did this myself, and originally tried to use django-
dynamicsites, but found it a little too touchy and not quite right for my
project. As a result, I ended up taking a little bit different approach.

My project has a "sites" module and in that a module for each unique site.
Each module has it's own settings.py and urls.py and templates directory. For
example:

    
    
    sites
        - __init__.py
        - site1
            - __init__.py
            - settings.py
            - urls.py
            - templates
                - base.html
        - site 2
            - __init__.py
            - settings.py
            - urls.py
            - templates
                - base.html
    

Each settings.py looks roughly like this:

    
    
    from myproject.settings import *
    
    SITE_ID = 1
    URL_CONF = 'sites.site1.urls'
    
    SITE_ROOT = os.path.dirname(__file__)
    TEMPLATE_DIRS = (
        os.path.join(SITE_ROOT, 'templates')
    )
    
    CACHE_MIDDLEWARE_KEY_PREFIX = 'site1'
    

So, what this does is import your projects settings file, and then overrides
the settings that are unique to the site. Then, all you have to do is make
sure whatever server you're using loads the particular site's settings.py
instead of the main project settings.py. I'm using a combo of nginx+Gunicorn,
so here's roughly how that config looks:

**site1.conf (nginx)**

    
    
    upstream site1 {
        server 127.0.0.1:8001 fail_timeout=0;
    }
    
    server {
        listen 80;
        server_name site1.domain.com;
    
        root /path/to/project/root;
    
        location / {
            try_files $uri @proxy;
        }
    
        location @proxy {
            proxy_pass_header Server;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Scheme $scheme;
            proxy_connect_timeout 10;
            proxy_read_timeout 30;
            proxy_pass http://site1;
            proxy_redirect off;
        }
    
    }
    

I use supervisor to manage the Gunicorn server, so here's my config for that:

**site1.conf (supervisor)**

    
    
    [program:site1]
    command=/path/to/virtualenv/bin/python manage.py run_gunicorn --settings=sites.site1.settings
    directory=/path/to/project/root
    user=www-data
    autostart=true
    autorestart=true
    redirect_stderr=True
    

The important part is that there's no fancy Django middleware or such checking
for particular hosts and going this way or that accordingly. You fire up a
Django instance for each on uwsgi, Gunicorn, etc. pointing to the right
settings.py file, and your webserver proxies the requests for each subdomain
to the matching upstream connection.

