Django 数据库基础
Django 项目初始化后默认使用 SQLite3,但在生产环境中,我们往往需要更强大的关系型数据库支持。除了单库连接,实际业务中常涉及读写分离、多数据库甚至主从架构。本文将重点介绍多数据库连接的配置方案。
多数据库连接配置
1. 定义数据源
在 settings.py 中配置 DATABASES 字典,可以定义多个数据库实例。这里以 MySQL 8.0 为例:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'localhost',
'PORT': '3306',
'NAME': 'db1',
'USER': 'root',
'PASSWORD': 'root',
},
'system': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'localhost',
'PORT': '3306',
'NAME': 'db2',
'USER': 'root',
'PASSWORD': 'root',
}
}
如果不想使用默认数据库,可以将 default 设为空或移除,仅保留自定义键名。
2. 配置数据库路由
为了让不同应用(App)的数据写入不同的数据库,我们需要编写数据库路由器。在 settings.py 同级目录创建 database_router.py 文件。
首先启用路由:
DATABASE_ROUTERS = ['database_router.DatabaseAppsRouter']
DATABASE_APPS_MAPPING = {
'mydefault': 'default',
'mysystem': 'system',
}
接着实现路由类逻辑:
from django.conf import settings
DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING
class DatabaseAppsRouter(object):
"""
控制不同模型在不同数据库上的操作。
若未在 DATABASE_APPS_MAPPING 中设置,则回退到 default 数据库。
"""
def db_for_read(self, model, **hints):
"""读取操作指向指定数据库"""
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
def db_for_write(self, model, **hints):
"""写入操作指向指定数据库"""
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
def allow_relation(self, obj1, obj2, **hints):
"""允许同一数据库内的关联"""
db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
if db_obj1 and db_obj2:
return db_obj1 == db_obj2
return None
def allow_migrate(self, db, app_label, model=None, **hints):
"""确保 App 只出现在对应的数据库中"""
if db in DATABASE_MAPPING.values():
return DATABASE_MAPPING.get(app_label) == db
elif app_label in DATABASE_MAPPING:
return False
return None
路由的核心逻辑是匹配模型的 app_label 与映射表。对于跨库关联,allow_relation 会限制只有同库模型才能建立外键关系。
3. 模型映射
在创建 Model 时,通过 Meta 类指定 app_label,使其对应到路由中的键名:
from django.db import models
class User(models.Model):
username = models.CharField(verbose_name="用户名", max_length=64)
password = models.CharField(verbose_name="用户密码", max_length=64)
class Meta:
db_table = "userInfo"
app_label = 'mysystem' # 对应路由中的 system 库
迁移管理
配置完成后,需要通过命令行将模型同步到数据库。
基础迁移
生成迁移文件并应用到指定数据库:
# 生成迁移文件
python manage.py makemigrations
# 迁移到默认库
python manage.py migrate
# 迁移到特定库
python manage.py migrate --database=app
python manage.py migrate --database=system
重置迁移文件
多次修改模型会导致迁移文件碎片化,此时可尝试重置结构:
-
检查当前迁移状态:
python manage.py showmigrations[x]表示已执行,[ ]表示未执行。 -
模拟回滚到初始状态(注意替换为你的 App 名称):
python manage.py migrate --fake mysystem zero -
清理旧的迁移文件(保留
__init__.py): 删除migrations文件夹下除__init__.py外的所有.py文件及__pycache__。 -
重新生成迁移:
python manage.py makemigrations -
验证 SQL 并执行迁移:
python manage.py sqlmigrate mysystem 0001_initial python manage.py migrate --database=system
手动管理表结构
对于已存在的系统表或特殊需求,可以通过设置 managed = False 让 Django 不再自动管理该表的增删改查:
class MyTable(models.Model):
# ... fields ...
class Meta:
managed = False
开启此选项后,Django 不会在迁移中创建或删除该表,适合对接遗留系统或手动维护的表结构。在使用前建议先熟悉 Django 框架自带的表结构及其用途,以便更好地进行手动控制。
