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
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 %-)
==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...
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 %-)
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..
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...
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 %-)
As noted on a different thread, I've logged this problem as #12767.
Yours,
Russ Magee %-)
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