在Django项目中,可能需要连接2个或多个数据库。我在项目中遇到了这种需求,文末参考文档中有更多的知识点;不过,我自己使用的是编写自己的Database Router。
首先,在setting.py文件中,需要配置好多个数据库,如:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'abc',
'USER': 'abc',
'PASSWORD': '123456',
'HOST': '192.168.100.100',
'PORT': 3306,
},
'bugzilla': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bugzilla',
'USER': 'def',
'PASSWORD': '123456',
'HOST': '192.168.100.101',
'PORT': 3306,
}
}
2. 编写Database Router,可以根据model的app_label来指定使用某个DB,如下(在db_router.py):
class BugzillaRouter(object):
"""
A router to control all database operations on models in the
bugzilla application.
"""
def db_for_read(self, model, **hints):
"""
Attempts to read bugzilla models go to bugzilla DB.
"""
if model._meta.app_label == 'bugzilla':
return 'bugzilla'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write bugzilla models go to bugzilla DB.
"""
if model._meta.app_label == 'bugzilla':
return 'bugzilla'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the bugzilla app is involved.
"""
if obj1._meta.app_label == 'bugzilla' or \
obj2._meta.app_label == 'bugzilla':
return True
return None
def allow_migrate(self, db, model):
"""
Make sure the bugzilla app only appears in the bugzilla database.
"""
if db == 'bugzilla':
return model._meta.app_label == 'bugzilla'
elif model._meta.app_label == 'bugzilla':
return False
def allow_syncdb(self, db, model):
if db == 'bugzilla' or model._meta.app_label == "bugzilla":
return False # we're not using syncdb on our bugzilla database
else: # but all other models/databases are fine
return True
return None
class AewRouter(object):
"""
A router to control all database operations on models in the
aew application.
"""
def db_for_read(self, model, **hints):
"""
Attempts to read aew models go to aew DB.
"""
if model._meta.app_label == 'aew':
return 'default'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write aew models go to aew DB.
"""
if model._meta.app_label == 'aew':
return 'default'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the aew app is involved.
"""
if obj1._meta.app_label == 'aew' or obj2._meta.app_label == 'aew':
return True
return None
def allow_migrate(self, db, model):
"""
Make sure the aew app only appears in the aew database.
"""
if db == 'default':
return model._meta.app_label == 'aew'
elif model._meta.app_label == 'aew':
return False
return None
3. 在settings.py文件中配置DB router,例如:
DATABASE_ROUTERS = [‘aew.db_router.BugzillaRouter’, ‘aew.db_router.AewRouter’]
注意这个是有顺序的(先匹配上的规则,就先生效)。
4. 在models中配置想用的model时,指定好app_label,如下:
class Products(models.Model):
'''
@note: sycn from bugzilla
'''
id = models.IntegerField(primary_key=True)
name = models.CharField(unique=True, max_length=64)
classification = models.ForeignKey(Classifications)
isactive = models.IntegerField()
class Meta:
app_label = 'aew'
db_table = 'products'
class Classifications(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(unique=True, max_length=64)
description = models.TextField(blank=True)
sortkey = models.IntegerField()
class Meta:
app_label = 'bugzilla'
managed = False
db_table = 'classifications'
这样配置的情况下,Products就是使用的default的DB,而Classifications就是使用的bugzilla DB.
参考资料:
https://docs.djangoproject.com/en/dev/topics/db/multi-db/
https://thenewcircle.com/s/post/1242/django_multiple_database_support