4

django使用多个数据库实现 - Se7eN_HOU

 1 year ago
source link: https://www.cnblogs.com/Se7eN-HOU/p/17339885.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一、说明:

  在开发 Django 项目的时候,很多时候都是使用一个数据库,即 settings 中只有 default 数据库,但是有一些项目确实也需要使用多个数据库,这样的项目,在数据库配置和使用的时候,就比较麻烦一点。

二、Django使用多个数据库中settings中的DATABASES的设置

  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'
    }
}

三、实现思路

  1. 多个应用对应多个数据库和一个应用对应多个数据库
    1. 情况一:项目有多个 应用app 且需要使用到多个数据库
    2. 情况二:项目只有一个应用app, 且但需要使用到多个数据库,
  2. 这两种情况的实现思路其实都是一样的,都是为每个数据库创建一个应用,即这个应用只对接一个数据库,如果这个应用不需要写任何业务逻辑的代码,也需要创建一个空的应用,主要是用来做数据库迁移的
  3. 核心思想就是:一个model类对应一个数据库,通过数据库路由和model定义时指定的all_label来实现。

四、案例实现

  第一步:创建需要的 应用app,并且在 INSTALLED_APPS 中引用

    其中db1_app这个应用主要是用来对接数据库db1的

    其中db2_app这个应用主要是用来对接数据库db2的

    其中test_app这个应用主要用来实现业务逻辑的

                 

751754-20230421135802745-1234046169.png

  第二步:创建 应用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

  第四步:在setting.py中配置 DATABASE_ROUTERS 指定自由路由文件:

#test_django为项目名,database_router为路由文件名,DatabaseAppsRouter为路由中创建的类名
DATABASE_ROUTERS = ['django_db_demo.database_router.DatabaseAppsRouter']

  第五步:创建model类

    说明: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对象,对应不用数据库的表。

    

751754-20230421113856410-1310647750.png

第五步:总结

  1. 创建多个数据库连接设置
  2. 创建多个数据与应用app的映射关系
  3. 创建数据库路由
  4. 创建model类的时候置指明app_label,即这个model是属于那个app,从而觉得迁移到那个数据库

侯哥语录:我曾经是一个职业教育者,现在是一个自由开发者。我希望我的分享可以和更多人一起进步。分享一段我喜欢的话给大家:"我所理解的自由不是想干什么就干什么,而是想不干什么就不干什么。当你还没有能力说不得时候,就努力让自己变得强大,拥有说不得权利。"

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK