Per application default database?

197 views
Skip to first unread message

Bill Hubauer

unread,
Jan 18, 2010, 11:04:02 AM1/18/10
to django-d...@googlegroups.com

Hi all,

One of the use cases that may be common for multiple database support is being able to combine multiple Django applications that require different databases into a single site. This is exactly what I need to do for one project. This can be done with the new multiple database support, but it feels heavy handed to me to require the "integrator" go through all of the application code and insert "using" specifiers. I also get nervous to about missing some places where it would be required.

I've reviewed the code related to the selection of the default database and think that it wouldn't be too hard to make it possible to do application specific defaults to database settings. It would mostly be refactoring the django.db.DEFAULT_DB_ALIAS constant into a function, and then deciding the best way to allow the user to specify a default database per application in the settings file.

Has there been any consideration or discussion of this type of functionality?

Regards,
Bill

Tobias McNulty

unread,
Jan 18, 2010, 11:20:06 AM1/18/10
to django-d...@googlegroups.com

There has been.  See:

http://groups.google.com/group/django-developers/browse_thread/thread/7904c7da7cb0085f/eb5a359e30307e89?lnk=gst&q=multidb+tobias#eb5a359e30307e89

If I recall correctly, the resolution was basically "not in this phase," i.e., this is something to be worked out in a future release of Django.

Tobias


--
Tobias McNulty
Caktus Consulting Group, LLC
P.O. Box 1454
Carrboro, NC 27510
(919) 951-0052
http://www.caktusgroup.com

Russell Keith-Magee

unread,
Jan 19, 2010, 10:35:50 AM1/19/10
to django-d...@googlegroups.com

You recall correctly :-)

The goal for 1.2 is to get enough of the plumbing in place so that
enthused individuals can use multi-db if they need to. The clean
public API that addresses will be added (hopefully) in 1.3, using the
experiences and guidance gathered from early adopters of the raw API.

Yours,
Russ Magee %-)

kmpm

unread,
Feb 2, 2010, 2:53:53 PM2/2/10
to Django developers
Wouldn't a database router like this sort of do the thing for now...

==settings.py==
DATABASE_ROUTERS = ['dbrouter.AppRouter',]
==dbrouter.py==
APPS_WITH_DB=('my_app_with_same_name_as_db',
)

class AppRouter(object):
"""A router to control all database operations on models in
that belongs to a app in APPS_WITH_DB"""

def db_for_read(self, model, **hints):
if model._meta.app_label in APPS_WITH_DB:
return model._meta.app_label
return None

def db_for_write(self, model, **hints):
if model._meta.app_label in APPS_WITH_DB:
return model._meta.app_label
return None

def allow_relation(self, obj1, obj2, **hints):
if (obj1._meta.app_label in APPS_WITH_DB) or
(obj2._meta.app_label in APPS_WITH_DB):
return True
return None

def allow_syncdb(self, db, model):
"Make sure the app only appears on the db where it belongs"
#print "db=%s, app=%s, model=%s" % (db, model._meta.app_label,
model)
if db in APPS_WITH_DB:
return db == model._meta.app_label
elif model._meta.app_label in APPS_WITH_DB:
return False
return None

On Jan 19, 4:35 pm, Russell Keith-Magee <freakboy3...@gmail.com>
wrote:


> On Tue, Jan 19, 2010 at 12:20 AM, Tobias McNulty <tob...@caktusgroup.com> wrote:
>

> > On Mon, Jan 18, 2010 at 11:04 AM, Bill Hubauer <bhuba...@gmail.com> wrote:
>
> >> One of the use cases that may be common for multiple database support is
> >> being able to combine multiple Django applications that require different
> >> databases into a single site.   This is exactly what I need to do for one
> >> project.   This can be done with the new multiple database support, but it
> >> feels heavy handed to me to require the "integrator" go through all of the

> >>applicationcode and insert "using" specifiers.   I also get nervous to


> >> about missing some places where it would be required.
>
> >> I've reviewed the code related to the selection of the default database
> >> and think that it wouldn't be too hard to make it possible to doapplication
> >> specific defaults to database settings.   It would mostly be refactoring the
> >> django.db.DEFAULT_DB_ALIAS constant into a function, and then deciding the
> >> best way to allow the user to specify a default databaseperapplicationin
> >> the settings file.
>
> >> Has there been any consideration or discussion of this type of
> >> functionality?
>
> > There has been.  See:
>

> >http://groups.google.com/group/django-developers/browse_thread/thread...

Russell Keith-Magee

unread,
Feb 3, 2010, 7:16:15 AM2/3/10
to django-d...@googlegroups.com
On Wed, Feb 3, 2010 at 3:53 AM, kmpm <pe...@birchroad.net> wrote:
> Wouldn't a database router like this sort of do the thing for now...

Yes - this is exactly what a router is designed for.

At the time I posted my last reply, routers didn't exist yet. I had to
implement routers in order to solve some other problems, but along the
way, I ended up implementing most of the stuff that I thought we would
need to defer to v1.3.

Yours
Russ Magee %-)

kmpm

unread,
Feb 3, 2010, 1:11:44 PM2/3/10
to Django developers
Hmm... strange.
I get a strange error when I tried to do this....
Something about a django_content_type relation which I don't have.
This probably happens when the "app" gets registerd in the auth
system.
Same error with both postgresql and sqlite3.

Databases are configured like this..
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydata', # Or path to database
file if using sqlite3.
'USER': 'postgres', # Not used with
sqlite3.
'PASSWORD': 'supersecret', # Not used with
sqlite3.
'HOST': 'localhost', # Set to empty
string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for
default. Not used with sqlite3.
},
'ads': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydata_ads',
'USER': 'postgres', # Not used with
sqlite3.
'PASSWORD': 'supersecret', # Not used with
sqlite3.
'HOST': 'localhost', # Set to empty
string for localhost. Not used with sqlite3.
'PORT': '',
}
}

Running a ./manage.py syncdb works as a dream but doesn't include the
adds app because of the router previously mentioned.

Here is what happens when I try to sync a database/app called ads.
./manage.py syncdb --database=ads
Creating table ads_entry
Traceback (most recent call last):
File "./manage.py", line 11, in <module>
execute_manager(settings)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/core/management/__init__.py", line 438, in
execute_manager
utility.execute()
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/core/management/__init__.py", line 379, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/core/management/base.py", line 195, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/core/management/base.py", line 222, in execute
output = self.handle(*args, **options)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/core/management/base.py", line 351, in handle
return self.handle_noargs(**options)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/core/management/commands/syncdb.py", line 97, in
handle_noargs
emit_post_sync_signal(created_models, verbosity, interactive, db)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/core/management/sql.py", line 190, in
emit_post_sync_signal
interactive=interactive, db=db)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/dispatch/dispatcher.py", line 166, in send
response = receiver(signal=self, sender=sender, **named)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/contrib/contenttypes/management.py", line 12, in
update_contenttypes
content_types = list(ContentType.objects.using(db).filter
(app_label=app.__name__.split('.')[-2]))
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/db/models/query.py", line 81, in __len__
self._result_cache.extend(list(self._iter))
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/db/models/query.py", line 267, in iterator
for row in compiler.results_iter():
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/db/models/sql/compiler.py", line 685, in results_iter
for rows in self.execute_sql(MULTI):
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/db/models/sql/compiler.py", line 740, in execute_sql
cursor.execute(sql, params)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/db/backends/util.py", line 19, in execute
return self.cursor.execute(sql, params)
File "/home/peterm/python/dalsland/local/py/lib/python2.6/site-
packages/django/db/backends/postgresql_psycopg2/base.py", line 44, in
execute
return self.cursor.execute(query, args)
django.db.utils.DatabaseError: relation "django_content_type" does not
exist
LINE 1: ..."."app_label", "django_content_type"."model" FROM
"django_co..

scastillo

unread,
Feb 3, 2010, 3:00:05 PM2/3/10
to Django developers
And what if i just want to have the same database but with different
users for each app on project?

On Jan 19, 10:35 am, Russell Keith-Magee <freakboy3...@gmail.com>
wrote:


> On Tue, Jan 19, 2010 at 12:20 AM, Tobias McNulty <tob...@caktusgroup.com> wrote:
>

> > On Mon, Jan 18, 2010 at 11:04 AM, Bill Hubauer <bhuba...@gmail.com> wrote:
>
> >> One of the use cases that may be common for multiple database support is
> >> being able to combine multiple Django applications that require different
> >> databases into a single site.   This is exactly what I need to do for one
> >> project.   This can be done with the new multiple database support, but it
> >> feels heavy handed to me to require the "integrator" go through all of the
> >> application code and insert "using" specifiers.   I also get nervous to
> >> about missing some places where it would be required.
>
> >> I've reviewed the code related to the selection of the default database
> >> and think that it wouldn't be too hard to make it possible to do application
> >> specific defaults to database settings.   It would mostly be refactoring the
> >> django.db.DEFAULT_DB_ALIAS constant into a function, and then deciding the
> >> best way to allow the user to specify a default database per application in
> >> the settings file.
>
> >> Has there been any consideration or discussion of this type of
> >> functionality?
>
> > There has been.  See:
>

> >http://groups.google.com/group/django-developers/browse_thread/thread...

Russell Keith-Magee

unread,
Feb 3, 2010, 7:13:22 PM2/3/10
to django-d...@googlegroups.com
On Thu, Feb 4, 2010 at 4:00 AM, scastillo <castill...@gmail.com> wrote:
> And what if i just want to have the same database but with different
> users for each app on project?

If, by "users" are you referring to the database login credentials,
you could set up a multiple connections to the same database, each
with a different login credential, and then use a router to choose the
database based on the application.

If you mean something else, you'll need to explain your use case a little more.

Yours,
Russ Magee %-)

Russell Keith-Magee

unread,
Feb 3, 2010, 7:14:24 PM2/3/10
to django-d...@googlegroups.com
On Thu, Feb 4, 2010 at 2:11 AM, kmpm <pe...@birchroad.net> wrote:
> Hmm... strange.
> I get a strange error when I tried to do this....
> Something about a django_content_type  relation which I don't have.
> This probably happens when the "app" gets registerd in the auth
> system.
> Same error with both postgresql and sqlite3.

As noted on a different thread, I've logged this problem as #12767.

Yours,
Russ Magee %-)

lasizoillo

unread,
Feb 20, 2010, 3:11:47 AM2/20/10
to django-d...@googlegroups.com
2010/2/3 kmpm <pe...@birchroad.net>:


As workaround I changed to this code in router:

def allow_syncdb(self, db, model):
"Make sure the auth app only appears on the 'geonames' db"
if db == 'geonames':
return model._meta.app_label == 'geonames' or \
model._meta.app_label == 'contenttypes' ##This is
the workaround
elif model._meta.app_label == 'geonames':
return False
return None


I want a separated geonames db, instead credentials db. But is
equivalent issue. It duplicates django_content_type table, but only
this.

I need execute syncdb on default database first.

Reggards,

Javi

Reply all
Reply to author
Forward
0 new messages