How does one set up multiple accounts with separate databases for Django on one server?
What options are there for installing Django such that multiple users (each with an "Account") can each have their own database?
The semantics are fairly intuitive. There may be more than one User for an Account. An Account has a unique database (and a database corresponds to an account). Picture WordpressMU. :)
I've considered this:
External solution - Multiplex to multiple servers/daemons
Multiple Django installations, with each Django installation / project corresponding to an account that sets its own DATABASE_NAME, e.g.
/bob /settings.py (contains DATABASE_NAME="bob") /sue /settings.py (contains DATABASE_NAME="sue")
Then having a Django instance running for each of bob and sue. I don't like this methodology- it feels brutish and it smells foul. But I'm confident it would work, and based on the suggestions it might be the cleanest, smartest way to do it.
The apps can be stored elsewhere; the only thing that need be unique to the django configuration is the settings.py (and even there, only DATABASE_NAME, etc. need be different, the rest can be imported).
(Incidentally, I'm using lighttpd and FastCGI.)
Internal solution - Django multiplexing database settings
On the other hand, I've thought of having one single Django installation, and
(a) Adding a "prefix_" to each database table, corresponding to account of the logged-in user; or
(b) Changing the database according to the account of the User that is logged in.
I'd be particularly interested in seeing the "Django way" to do these (hoping that it's something dead-simple). For example, middleware that takes a Request's User and changes the django.conf.SETTINGS['DATABASE_NAME'] to the database for this user's account.
This raises red flags, viz. Is this thread-safe? i.e. Does changing django.conf.SETTINGS affect other processes? Is there just an inherent danger in changing django.conf.SETTINGS -- would the DB connection be setup already? Is restarting the DB connection part of the public API? -- I'm going to have a look at the Django source when I look to this problem again.
I'm conscious that 2(a) and (b) could require User authentication to be stored and accessed in a different mechanism that the core.
For now, I'm going to go with the external mapping at the webserver layer- it's simplest and cleanest for now. However, I don't like the idea of FastCGI daemons running for every account- it seems to needlessly waste memory, particularly if there will be 2000+ accounts. However, I'd like to keep this discussion open as it's an interesting problem and the solution doesn't seem ideal for certain cases.
Comments duly appreciated. Cheers
The Django way would definitely be to have separate installations with their own database name (#1). #2 would involve quite a bit of hacking with the ORM, and even then I'm not quite sure it's possible at all.
But mind you, you don't need a WHOLE new installation of all the site's models/views/templates for each user, just a new settings.py with all the appropriate paths to the common source files. Plus, to run all these installations in Apache, do it the way I do here:
<VirtualHost 18.104.22.168> DocumentRoot /www/site1 ServerName site1.com <Location /> SetHandler python-program SetEnv DJANGO_SETTINGS_MODULE site1.settings PythonPath "['/www'] + sys.path" PythonDebug On PythonInterpreter site1 </Location> </VirtualHost> <VirtualHost 22.214.171.124> DocumentRoot /www/site2 ServerName site2.com <Location /> SetHandler python-program SetEnv DJANGO_SETTINGS_MODULE site2.settings PythonPath "['/www'] + sys.path" PythonDebug On PythonInterpreter site2 </Location> </VirtualHost>
assuming you've got /www/site1/settings.py, www/site2/settings.py and so on...
Of course, you now need to have a main site where people log in, that then redirects you to the appropriate site (here I've just put it as "site1.com", "site2.com", but you get the idea.)
The Django ORM doesn't provide multiple database support classes, but it is definitely possible - you'll have to write a custom manager and make a few other tweaks. Eric Florenzano has a great article with detailed code samples: