You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中优雅切换数据库配置?

Django启动时优雅切换数据库的方案

问题背景

Django的settings.py中DATABASES字典支持存储多套数据库配置:

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'test': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testing',
        'USER': 'bert',
        'PASSWORD': '***',
        'HOST': 'remotemysql.com',
        'PORT': '3306',
    },
    'dev': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'development',
        'USER': 'ernie',
        'PASSWORD': '***',
        'HOST': 'remotemysql.com',
        'PORT': '3306',
    },
    ...
}

原本期望通过设置独立变量(如USE_THIS_DB = 'test')快速切换测试、开发、生产数据库,但官方没有直接提供该选项。目前手动修改DATABASES中配置项名称的方式繁琐易出错,且缺乏可移植性。

以下是几种优雅的切换方案:

方案1:环境变量动态指定默认数据库

在settings.py中读取环境变量,动态将目标数据库配置设为default,无需修改代码即可切换:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# 先定义所有数据库的完整配置
DB_CONFIGS = {
    'sqlite': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    },
    'test': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testing',
        'USER': 'bert',
        'PASSWORD': os.getenv('DB_TEST_PASSWORD'),  # 建议密码从环境变量读取,避免硬编码
        'HOST': 'remotemysql.com',
        'PORT': '3306',
    },
    'dev': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'development',
        'USER': 'ernie',
        'PASSWORD': os.getenv('DB_DEV_PASSWORD'),
        'HOST': 'remotemysql.com',
        'PORT': '3306',
    },
}

# 从环境变量获取要激活的数据库,默认使用sqlite
ACTIVE_DB = os.getenv('DJANGO_ACTIVE_DB', 'sqlite')
DATABASES = {'default': DB_CONFIGS[ACTIVE_DB]}

启动项目时通过环境变量指定数据库:

# Linux/macOS终端
DJANGO_ACTIVE_DB=test python manage.py runserver

# Windows PowerShell
$env:DJANGO_ACTIVE_DB='test'; python manage.py runserver

方案2:拆分多Settings文件

将配置按环境拆分,每个环境对应一个独立的settings文件,继承通用配置并指定默认数据库:

  1. 在项目的settings目录下创建以下文件:

    • base.py:存放通用配置(如INSTALLED_APPS、MIDDLEWARE)和所有数据库定义
    • dev.py:开发环境配置
    • test.py:测试环境配置
    • prod.py:生产环境配置
  2. base.py核心内容:

# base.py
import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

# 通用配置
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    ...
]

# 所有数据库配置
DATABASES = {
    'sqlite': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    },
    'test': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testing',
        'USER': 'bert',
        'PASSWORD': os.getenv('DB_TEST_PASSWORD'),
        'HOST': 'remotemysql.com',
        'PORT': '3306',
    },
    'dev': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'development',
        'USER': 'ernie',
        'PASSWORD': os.getenv('DB_DEV_PASSWORD'),
        'HOST': 'remotemysql.com',
        'PORT': '3306',
    },
}
  1. test.py内容(继承base并切换数据库):
# test.py
from .base import *

# 设置默认数据库为测试库
DATABASES['default'] = DATABASES['test']

# 添加测试环境专属配置
DEBUG = True
ALLOWED_HOSTS = ['localhost']

启动时指定对应settings文件:

python manage.py runserver --settings=myproject.settings.test

方案3:自定义命令行参数(修改manage.py)

如果希望直接通过命令行参数指定数据库,可以修改项目根目录的manage.py,添加自定义参数解析:

#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
import argparse

def main():
    # 解析自定义的--use-db参数
    parser = argparse.ArgumentParser()
    parser.add_argument('--use-db', default='sqlite', choices=['sqlite', 'test', 'dev'])
    args, remaining_args = parser.parse_known_args()
    
    # 将选中的数据库写入环境变量,供settings.py读取
    os.environ['DJANGO_ACTIVE_DB'] = args.use_db
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line([sys.argv[0]] + remaining_args)

if __name__ == '__main__':
    main()

启动时直接传递参数:

python manage.py runserver --use-db=test

内容的提问来源于stack exchange,提问作者Darien Marks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:55:31