首页 > 数据库 >django使用多个数据库实现

django使用多个数据库实现

时间:2023-04-21 12:15:41浏览次数:38  
标签:多个 DATABASE 数据库 db django model label app

一、说明:

  在开发 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这个应用主要用来实现业务逻辑的

                 

 

  第二步:创建 应用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对应那个数据库
        db_table = "sqlite_test_table"   # 自定义的表名

class Db1Model(models.Model):
    """帐号和用户关联"""

    db1_name = models.CharField(max_length=20)
    class Meta:
        # 当前这个Db1Model 定义的数据库的表将会创建在 db1_app 对应的 db1 数据库中
        app_label = "db1_app"        # 当有多个数据库链接的时候,要通过app_label 来区分这个model对应那个数据库
        db_table = "db1_test_table"    # 自定义的表名

class Db2Model(models.Model):
    """帐号和用户关联"""

    db2_name = models.CharField(max_length=20)
    class Meta:
        # 当前这个Db2Model 定义的数据库的表将会创建在 db2_app 对应的 db1 数据库中
        app_label = "db2_app"       # 当有多个数据库链接的时候,要通过app_label 来区分这个model对应那个数据库
        db_table = "db2_test_table"   # 自定义的表名

  

  第六步:数据迁移

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

    

 第五步:总结

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

标签:多个,DATABASE,数据库,db,django,model,label,app
From: https://www.cnblogs.com/Se7eN-HOU/p/17339885.html

相关文章

  • 全平台数据(数据库)管理工具 DataCap 管理 Rainbond 上的所有数据库
    DataCap是用于数据转换、集成和可视化的集成软件,支持多种数据源、文件类型、大数据相关数据库、关系数据库、NoSQL数据库等。通过该DataCap可以实现对多个数据源的管理,对数据源下的数据进行各种操作转换,制作数据图表,监控数据源等功能。在Rainbond上部署DataCap前提安装Ra......
  • springmvc 链接数据库错误
    1.Causedby:org.xml.sax.SAXParseException:cos-all-limited.1.2:An''all''modelgroupmustappearinaparticlewith'{'minoccurs'}'='{'maxoccurs'}'=1,andthatparticlemustbepartofapa......
  • 多个DataTable的合并成一个新表
    https://www.cnblogs.com/JuneZhang/archive/2011/12/11/2284243.html有时我们知道了两个DataTable1和DataTable2,我们希望将它们合并为一个新的DataTable(下面的例子中命名为了newDataTable),这就分为两种情况:DataTable1和DataTable2结构相同、DataTable1和DataTable2结构不同,下面分......
  • easyExcel导出单个文件多个sheet页-注解方式
    easyExcel注解方式导出,为什么要用注解方式?注解方式更简单、更方便,相比非注解的方式减少了大量代码。但是,注解方式不够灵活,精确度也不高,比如列宽,注解方式仅支持int类型,最大255个字符,而非注解方式就要精确的多,可以随意设置。所以,对于要求比较高的、复杂的Excel,还是推荐使用非注解......
  • 数据库关联查询(左连接、右连接)
    在项目中用到多表联合查询,发现2个现象,今天解决这2个疑问:1、left join连接2张表,on后的条件第一个生效,用and连接的其他条件不生效;2、一旦加上where,则显示的结果等同于inner join;先写结论:过滤条件放在:where后面:是先连接然生成临时查询结果,然后再筛选on后面:先根据条件过滤筛选......
  • Django框架——手写web框架、wsgiref模块、动静态网页、jinja2模块、主流web框架、Dja
    web应用'''通过浏览器访问的应用程序!!!'''1.两种模式c/sb/s B/S:browser---------------->server2.web应用程序的有点 2.1只需要一个浏览器即可2.2 节省资源2.3 他们不需要更新,因为所有新的特性都在服务器上执行3.web应用程序的缺点 #特别依赖服务端程序的健壮......
  • 非关系型数据库安装-redis安装
    linux安装redis最新稳定版本原创 PHP星 编程经验共享 2023-03-1608:00 发表于广东收录于合集#linux18个#redis5个在安装redis之前我们需要提前安装编译安装需要的扩展库,例如:gcc,make等。但是最新版本要求需要python3的支持,所以我们还需要安装python3.1.安装......
  • android8 rk3399 同时支持多个USB摄像头
    文章目录一、前文二、CameraHal_Module.h三、CameraHal_Module.cpp四、编译&烧录Image五、App验证一、前文Android系统默认支持2个摄像头,一个前置摄像头,一个后置摄像头需要支持数量更多的摄像头,得修改AndroidHal层的代码二、CameraHal_Module.h修改CAMERAS_SUPPORT_MAX三、Camer......
  • mysql数据库学习1-cmd中乱码怎么办
    由于今天学习orcal,于是便顺便看下mysql,不看不知道,一看吓一跳,自己竟然不知道怎么用cmd登陆mysql。荒废了如此!首先,我们在cmd中要输入用户名和密码,此处的登陆方式不同于sqlplus;mysql-u用户名-p密码在查看当前用户下的表列表时,发现有几个是乱码,因为实在navicat中创建的,所以在编......
  • django获取当前用户提交到数据库的最新一条记录
    比如想获取最新一条数据的更新时间,datas返回的是一个QuerySet,是一个查询集可能用了filter,当用.last()返回最后一条记录时报错  objectisnotiterable然后用reverse()加上切片获取最后一条数据:reverse按倒序排列deflasttime(self):utime=FollowNote.objects.filte......