在django中配置多个数据源

0
(0)

我们公司的业务系统比较复杂,多个业务系统使用了不同的数据库,有些业务需要跨库访问,并且没有统一的后台管理系统,以应对常规的信息维护。这个场景需要一个能够快递实现增删改查的框架,比如django,配合强大的admin能力,快速的搭建出可用的系统。碰到的第一个问题就是管理多数据库。

在django文档中,使用DATABASE_ROUTERS配置,支持多数据库链接,以下是我项目中用到的代码:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb',
        'HOST': '192.168.0.2',
        'PORT': 3306,
        'USER': 'myuser1',
        'PASSWORD': 'mypassword1',
    },
    'mydb1': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb1',
        'HOST': '192.168.0.3',
        'PORT': 3306,
        'USER': 'myuser1',
        'PASSWORD': 'mypassword1',
    },
    'mydb2': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb2',
        'HOST': '192.168.0.3',
        'PORT': 3306,
        'USER': 'myuser1',
        'PASSWORD': 'mypassword1',
    },  
}

settngs.py文件中,DATABASES段定义多个数据库

在我的项目目录下创建文件 auth_router.py,其中定义类AuthRouter; 另一个文件 apps_router.py中定义类AppsRouter。其中auth_router.py是为了让django的基础app都访问默认库 default
目录结构如下:

myapp

    myapp

        __init__.py

        settings.py

        auth_router.py

        apps_router.py


接下来,在settings.py中定义DATABASE_ROUTERS和DATABASE_APPS_MAPPING

DATABASE_ROUTERS = ['myapp.auth_router.AuthRouter', 'myapp.apps_router.AppsRouter']

DATABASE_APPS_MAPPING = {
    'myapp1': 'mydb1',
    'myapp2': 'mydb2',
    ...
}

最后,在每个应用(myapp1, myapp2)的 models.py中定义Model时,使用app_label属性定义为所属的app。

class MyModel(models.Model):
    ...
    class Meta:
        app_label = 'myapp1'

程序运行的时候,会根据Model的app_label属性找到对应的app,从DATABASE_APPS_MAPPING中找到app对应的数据库配置,使用该数据库配置读取数据。

从django的文档中可以发现,使用DATABASE_ROUTER还可以配置读写分离的数据源,本例中没有涉及到。

附1 auth_router.py

class AuthRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """
    route_app_labels = {'admin', 'auth', 'contenttypes', 'sessions', 'logentrys'}

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'default'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'default'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps is
        involved.
        """
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth and contenttypes apps only appear in the
        'auth_db' database.
        """
        if app_label in self.route_app_labels:
            return db == 'default'
        return None

附2 apps_router.py

from django.conf import settings
 
DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING
 
 
class AppsRouter(object):
    """
    A router to control all database operations on models for different
    databases.
 
    In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
    will fallback to the `default` database.
 
    Settings example:
 
    DATABASE_APPS_MAPPING = {'app1': 'db1', 'app2': 'db2'}
    """
 
    def db_for_read(self, model, **hints):
        """Point all read operations to the specific database."""
        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None
 
    def db_for_write(self, model, **hints):
        """Point all write operations to the specific database."""
        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None
 
    def allow_relation(self, obj1, obj2, **hints):
        """Allow any relation between apps that use the same database."""
        db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
        db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
        if db_obj1 and db_obj2:
            # 20221015,如果前三位相同,也允许连接
            if db_obj1 == db_obj2 or db_obj1[:3] == db_obj2[:3]:
                return True
            else:
                return False
        return None
 
    def allow_migrate(self, db, app_label, model=None, **hints):
        """
        All non-auth models end up in this pool.
        """
        if DATABASE_MAPPING.get(app_label) == db:
            return True
        elif app_label in DATABASE_MAPPING:
            return False
        return None

参考链接: https://docs.djangoproject.com/zh-hans/5.2/topics/db/multi-db/#topics-db-multi-db-routing

2025/9/3 北京,上东廓

这篇文章有用吗?

点击星号为它评分!

平均评分 0 / 5. 投票数: 0

到目前为止还没有投票!成为第一位评论此文章。

很抱歉,这篇文章对您没有用!

让我们改善这篇文章!

告诉我们我们如何改善这篇文章?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注