问题
I've been trying to setup Django 1.4.3 to use multiple DBs, but for the life of me I can't make it to work. I read the documentation and posts on SO, and did the following:
1) Add a second DB configuration in settings.py
, as follows:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': '/tmp/django.db',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
},
'db1' : {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db1',
'USER': 'fake',
'PASSWORD': 'fake',
'HOST': 'fake.host.com',
'PORT': '3306',
},
}
2) Create a routers.py
and define a DB router as follows
(Note: According to SO posts, if you define a DB router in models.py
, the router will not work)
class DBRouter(object):
def db_for_read(self, model, **hints):
return 'db1'
def db_for_write(self, model, **hints):
return 'db1'
def allow_syncdb(self, db, model):
return 'db1'
3) Add the following lines to settings.py
(Note: According to SO posts, these lines must be AFTER the DATABASES
configurations
from django.db import connections
DATABASE_ROUTERS = ['fakeproject.routers.DBRouter',]
This was wrong. Do NOT put from django.db import connections
here as it prevents the router to be registered
My symptoms:
Apparently, all my calls are routed through the default DB. Details below:
Both DB settings work (I can perform
manage.py indpectdb --database db1
successfullyDATABASE_ROUTERS
setting does not generate any complains (even if I put a wrong path to the DB router, or even a non-string object)When I attempt to access my objects via
manage.py shell
, I can doMyModel.objects.all()
but when I actually try to iterate it, I'm toldno such table
. The default DB does not have that table, but 'db1' clearly has it as I generated the model by usinginspectdb
on it. As a proof, if I swap the DB configuration betweendb1
anddefault
, I can access the object without problems.
Any help highly appreciated!
回答1:
I found out that the statement in step 3 "from django.db import connections
" was preventing the DB router to be registered. When I removed this statement, the router was registered and stuff started to work as expected.
回答2:
I think the problem is probably arising because your routers.py
only returns a reference to 'db1'
but as you say you're only being routed to 'default'
I'm unsure (I would expect it to be the only routed to 'db1'
.
In routers.py
create a master router class, and then subclass for each DB - and initialise with an app_label
string so you can set them apart.
class MasterRouter(object):
def __init__(self, app_label):
super(MasterRouter, self).__init__()
self.app_label = app_label
def db_for_read(self, model, **hints):
if model._meta.app_label == self.app_label:
return self.app_label
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == self.app_label:
return self.app_label
return None
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == self.app_label or obj2._meta.app_label == self.app_label:
return True
return None
def allow_syncdb(self, db, model):
if db == 'default':
return model._meta.app_label == self.app_label
elif model._meta.app_label == self.app_label:
return False
return None
class DefaultRouter(MasterRouter):
def __init__(self):
super(DefaultRouter, self).__init__('default')
class DB1Router(MasterRouter):
def __init__(self):
super(DB1Router, self).__init__('db1')
and then in your settings.py
declare the routers
DATABASE_ROUTERS = [ 'routers.DefaultRouter', 'routers.DB1Router' ]
ofcourse, you'll probably want to set up your MasterRouter
class overrides differently.
来源:https://stackoverflow.com/questions/13988432/how-to-use-db-router-in-django-1-4