在Django项目中,可能需要连接2个或多个数据库。我在项目中遇到了这种需求,文末参考文档中有更多的知识点;不过,我自己使用的是编写自己的Database Router。
首先,在setting.py文件中,需要配置好多个数据库,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
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,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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