在开发 Django 项目的时候,很多时候都是使用一个数据库,即 settings 中只有 default 数据库,但是有一些项目确实也需要使用多个数据库,这样的项目,在数据库配置和使用的时候,就比较麻烦一点。
2.1 默认只是用一个数据库时 DATABASES 的设置(以 SQLite 为例)
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'db.sqlite3', } }
2.2 Django 数据库支持的 ENGINE 类型
'django.db.backends.postgresql'
'django.db.backends.mysql'
'django.db.backends.sqlite3'
'django.db.backends.oracle'
2.3 设置了多个数据库后 settings 中的 DATABASES 的设置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'db.sqlite3', }, 'db1': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mysql_test_db1', 'USER': 'root', 'PASSWORD': 'Se7eN521', 'HOST': '127.0.0.1', 'PORT': '3306' }, 'db2': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mysql_test_db2', 'USER': 'root', 'PASSWORD': 'Se7eN521', 'HOST': '127.0.0.1', 'PORT': '3306' } }
其中db1_app这个应用主要是用来对接数据库db1的
其中db2_app这个应用主要是用来对接数据库db2的
其中test_app这个应用主要用来实现业务逻辑的
在settings.py 文件夹中设置 DATABASE_APPS_MAPPING 的字典,里面主要是配置 应用app 和数据库的对应关系
DATABASE_APPS_MAPPING = { "db1_app": "db1", # db1_app 对应 db1 数据库 "db2_app": "db2" # db2_app 对应 db2 数据库 }
在项目的主文件夹即 settings.py 的同目录下创建一个 database_router.py 文件,该文件的作用就是给不同应用app 配置不同的数据库。
# _*_ coding:utf-8 _*_ # @Time : 2023/4/20 5:37 下午 from django.conf import settings DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING print('DATABASE_MAPPING = {}'.format(DATABASE_MAPPING)) class DatabaseAppsRouter(object): # 设置 应用app 读取时数据库的设置 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: if db_obj1 == db_obj2: return True else: return False return None def allow_migrate(self, db, app_label, model_name=None, **hints): """ Make sure that apps only appear in the related database. 根据app_label的值只在相应的数据库中创建一个表,如果删除该def或 不指定过滤条件,则一个Model会在每个数据库里都创建一个表。 """ if db in DATABASE_MAPPING.values():return DATABASE_MAPPING.get(app_label) == db elif app_label in DATABASE_MAPPING: return False return None
#test_django为项目名,database_router为路由文件名,DatabaseAppsRouter为路由中创建的类名 DATABASE_ROUTERS = ['django_db_demo.database_router.DatabaseAppsRouter']
说明:model 可以根据需要卸载任何一个应用app的model.py文件中,也可以分散写在多个应用的model.py中,这个根据自己的需要即可,但是如何推荐一定要在model类的Meta中指定app_label。不然会全部将表创建到default数据库中
from django.db import models class SqliteModel(models.Model): """帐号和用户关联""" sqlite_name = models.CharField(max_length=20) class Meta: # 当前这个 SqliteModel 定义的数据库的表将会创建在test_app 对应的default 数据库中 app_label = "test_app" # 当有多个数据库链接的时候,要通过app_label 来区分这个model对应那个数据库 class Db1Model(models.Model): """帐号和用户关联""" db1_name = models.CharField(max_length=20) class Meta: # 当前这个Db1Model 定义的数据库的表将会创建在 db1_app 对应的 db1 数据库中 app_label = "db1_app" # 当有多个数据库链接的时候,要通过app_label 来区分这个model对应那个数据库 class Db2Model(models.Model): """帐号和用户关联""" db2_name = models.CharField(max_length=20) class Meta: # 当前这个Db2Model 定义的数据库的表将会创建在 db2_app 对应的 db1 数据库中 app_label = "db2_app" # 当有多个数据库链接的时候,要通过app_label 来区分这个model对应那个数据库
python3 manage.py makemigrations python3 manage.py migrate --database=default # 当有多个数据库,需要迁移多次 python3 manage.py migrate --database=db1 python3 manage.py migrate --database=db2
model对应的表,分别迁移到不同的数据库成功,剩下的增删改查的就正常引入model对象即可,这样就实现了,不同的model对象,对应不用数据库的表。