免责声明

本站所有资源、内容均为转载整合,仅供学习与研究使用

本站涉及的收费项目,仅为资源整理、收集及维护成本,并非软件或内容本身的费用

请在学习研究后自觉删除相关内容,请勿用于商业用途或非法传播,因未及时删除或违规使用所产生的一切法律责任与后果,由使用者自行承担。

如需用于其他用途,请购买正版授权,支持原作者

若本站内容侵犯了您的合法权益,请通过邮箱 admin@zx-shop.com.cn 联系站长,我们将在第一时间核实并处理删除,感谢您的理解与配合!

python django切换数据库的几种方法

你想要在配置了多个数据库的 Django 项目中,切换使用第二个数据库,我会分「全局默认切换」和「指定操作使用第二个库」两种场景告诉你具体方法,满足不同使用需求。

一、先明确你的数据库配置结构

首先确认你在 settings.py 中的 DATABASES 配置格式(示例如下),假设第二个数据库的别名是 db2(你可以替换成自己的别名,比如 secondary):

# settings.py
DATABASES = {
    # 第一个默认数据库(别名 default)
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db1',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306',
    },
    # 第二个数据库(别名 db2)
    'db2': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db2',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

二、场景1:全局默认切换到第二个数据库

如果你想让整个项目默认使用第二个数据库(所有未指定库的操作都走 db2),直接修改 DATABASESdefault 的配置为第二个库的信息即可:

# 修改后的 settings.py
DATABASES = {
    # 将 default 指向原来的第二个数据库
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db2',  # 原 db2 的库名
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306',
    },
    # 原第一个数据库(可选保留,别名可自定义)
    'db1': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db1',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

修改后重启项目,所有 ORM 操作(如 Model.objects.all())都会默认使用第二个数据库。

三、场景2:仅指定操作使用第二个数据库(推荐,不影响全局)

如果不想改变全局默认库,只是部分操作(如查询/新增数据)使用第二个数据库,有 3 种常用方式:

方式1:单个查询/操作指定数据库

使用 using() 方法指定要使用的数据库别名(如 db2),适用于零散的操作:

# 示例:查询 User 模型的数据,使用 db2 数据库
from django.contrib.auth.models import User

# 查询
users = User.objects.using('db2').all()
# 新增
user = User(username='test', email='test@xxx.com')
user.save(using='db2')  # 保存到 db2
# 更新
User.objects.using('db2').filter(id=1).update(username='new_name')
# 删除
User.objects.using('db2').filter(id=1).delete()

方式2:模型类默认使用第二个数据库

如果某个模型始终要使用第二个数据库,可在模型类中定义 using 方法:

# models.py
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    # 重写 using 方法,指定默认使用 db2
    def using(self, alias=None):
        return super().using(alias or 'db2')

# 使用时无需手动指定 using,默认走 db2
product = Product(name='手机', price=2999)
product.save()  # 自动保存到 db2
products = Product.objects.all()  # 自动从 db2 查询

方式3:使用数据库路由(适用于多模型批量指定)

如果多个模型需要统一使用第二个数据库,可配置数据库路由(推荐大型项目):

  1. 在项目中创建 routers.py 文件:

    # routers.py
    class DB2Router:
        """路由类:指定模型使用 db2 数据库"""
        # 需要使用 db2 的模型列表(替换为你的模型路径)
        db2_models = ['app1.models.Product', 'app2.models.Order']
    
        def db_for_read(self, model, **hints):
            """读操作指定数据库"""
            model_path = f"{model.__module__}.{model.__name__}"
            if model_path in self.db2_models:
                return 'db2'
            return 'default'  # 其他模型用默认库
    
        def db_for_write(self, model, **hints):
            """写操作指定数据库"""
            model_path = f"{model.__module__}.{model.__name__}"
            if model_path in self.db2_models:
                return 'db2'
            return 'default'
    
        def allow_relation(self, obj1, obj2, **hints):
            """允许关联关系"""
            return True
    
        def allow_migrate(self, db, app_label, model_name=None, **hints):
            """允许迁移"""
            return True
    # routers.py(比较完善)
    from django.apps import apps
    
    class UniversalDatabaseRouter:
        """
        通用数据库路由类:支持多库配置,可批量/全部指定模型
        配置说明:
        - key:数据库别名(如 'db2')
        - value:模型列表(['app1.models.Model1'])或 '__all__'(表示全部模型)
        """
        # 核心配置:数据库别名 → 对应模型(支持__all__表示全部模型)
        DB_MODEL_MAP = {
            # 示例1:第二个数据库(db2)接管全部模型
            'db2': '__all__',  
            # 示例2:部分模型映射到其他数据库(按需开启)
            # 'db3': ['app2.models.Order', 'app3.models.Product'],
            # 示例3:默认库(default)接管剩余未配置的模型(无需写)
        }
    
        def _get_db_alias_for_model(self, model):
            """核心辅助方法:根据模型获取对应的数据库别名"""
            # 拼接模型的完整路径(如 'app1.models.User')
            model_full_path = f"{model.__module__}.{model.__name__}"
            
            # 遍历配置,匹配模型对应的数据库
            for db_alias, model_config in self.DB_MODEL_MAP.items():
                # 配置为 __all__ → 全部模型都用该数据库
                if model_config == '__all__':
                    return db_alias
                # 配置为模型列表 → 匹配到则返回对应数据库
                if model_full_path in model_config:
                    return db_alias
            
            # 未匹配到 → 使用默认数据库
            return 'default'
    
        def db_for_read(self, model, **hints):
            """读操作:返回模型对应的数据库别名"""
            return self._get_db_alias_for_model(model)
    
        def db_for_write(self, model, **hints):
            """写操作:返回模型对应的数据库别名(和读保持一致)"""
            return self._get_db_alias_for_model(model)
    
        def allow_relation(self, obj1, obj2, **hints):
            """允许关联关系:只要两个对象的数据库相同,就允许关联"""
            db1 = self._get_db_alias_for_model(obj1.__class__)
            db2 = self._get_db_alias_for_model(obj2.__class__)
            return db1 == db2
    
        def allow_migrate(self, db, app_label, model_name=None, **hints):
            """
            允许迁移:控制模型是否能在指定数据库上执行 migrate
            - db:当前要迁移的数据库别名
            - model_name:模型名(如 'user')
            """
            # 无模型名 → 允许迁移
            if not model_name:
                return True
            
            # 获取模型类(通过app_label和model_name)
            try:
                model = apps.get_model(app_label, model_name)
            except LookupError:
                return False
            
            # 模型对应的数据库 == 当前迁移的数据库 → 允许迁移
            target_db = self._get_db_alias_for_model(model)
            return db == target_db
    
        def allow_migrate_model(self, db, model):
            """Django 4.2+ 新增方法:细化模型迁移权限(兼容用)"""
            target_db = self._get_db_alias_for_model(model)
            return db == target_db
    需求场景 配置方式(修改 DB_MODEL_MAP
    全部模型用第二个数据库(db2) 'db2': '__all__'
    部分模型用 db2 'db2': ['app1.models.Product', 'app2.models.Order']
    多数据库分别映射不同模型 'db2': ['app1.models.A'], 'db3': ['app2.models.B']
  2. settings.py 中注册路由:

    # settings.py
    DATABASE_ROUTERS = ['项目名.routers.DB2Router']  # 替换为你的 routers.py 路径

配置后,db2_models 中的模型会自动使用 db2 数据库,其他模型仍用默认库。

四、验证是否切换成功

可以通过以下方式确认操作是否走第二个数据库:

  1. 查看数据库日志(如 MySQL 日志),确认 SQL 语句执行的库名;

  2. 在第二个数据库中手动新增一条测试数据,用代码查询验证是否能获取到。

总结

  1. 全局切换:直接修改 settings.pyDATABASES['default'] 为第二个库的配置,简单但影响所有操作;

  2. 局部切换:零散操作用 using('db2'),单个模型重写 using 方法,多模型用数据库路由(推荐);

  3. 核心关键:所有指定操作的核心是第二个数据库的别名(如示例中的 db2),需与 settings.py 中的配置一致。

请登录后发表评论

    没有回复内容