Django——多个数据库

官方文档:https://docs.djangoproject.com/en/3.2/topics/db/multi-db/

主要介绍Django 对与多个数据库交互的支持。

1. 数据库服务器 DATABASES

在Django中使用多个数据库的第一步是告诉Django将要使用的数据库服务器。 这是通过使用 DATABASES 设置完成的。 这个设置将数据库别名映射到特定连接的设置字典中,别名是在Django中引用特定数据库的一种方式。 内部字典中的设置在DATABASES文档中有完整的描述。

数据库可以有您选择的任何别名。 但是,别名默认值有特殊的意义。 当没有选择其他数据库时,Django会使用default 别名的数据库。

下面是 settings.py 代码片段的一个例子,它定义了两个数据库——一个默认的 PostgreSQL 数据库和一个名为users的 MySQL 数据库:

DATABASES = {'default': {'NAME': 'app_data','ENGINE': 'django.db.backends.postgresql','USER': 'postgres_user','PASSWORD': 's3krit'},'users': {'NAME': 'user_data','ENGINE': 'django.db.backends.mysql','USER': 'mysql_user','PASSWORD': 'priv4te'}
}

如果默认数据库的概念在项目的上下文中没有意义,那么您需要始终谨慎地指定要使用的数据库。 Django要求定义一个默认的数据库条目,但是如果不使用的话,参数字典可以保留为空。 要做到这一点,你必须为所有应用程序的模型设置 DATABASE_ROUTERS,包括你正在使用的任何应用程序和第三方应用程序的模型,这样查询就不会路由到默认数据库

下面是 settings.py 代码段的一个示例,它定义了两个非默认数据库,默认条目故意为空:

DATABASES = {'default': {},'users': {'NAME': 'user_data','ENGINE': 'django.db.backends.mysql','USER': 'mysql_user','PASSWORD': 'superS3cret'},'customers': {'NAME': 'customer_data','ENGINE': 'django.db.backends.mysql','USER': 'mysql_cust','PASSWORD': 'veryPriv@ate'}
}

如果你试图访问一个没有在 database 设置中定义的数据库,Django会抛出 Django.utils.connection. connectiondoesnotexist 异常。

2. 同步数据库

迁移管理命令一次操作一个数据库

(default是默认的数据库,在这里可以为{},但是一旦为空不可以执行 python manage.py migrate)

默认情况下,它在默认数据库上操作,但是通过提供 ——database 选项,可以告诉它同步一个不同的数据库。 因此,要将上面第一个例子中的所有模型同步到所有数据库,

您需要调用:

python manage.py makemigrations   # 生成迁移文件
python manage.py migrate --database=users

如果您不希望将每个应用程序同步到特定的数据库,那么可以定义一个数据库路由器,该路由器实现一个限制特定模型可用性的策略。

如果与上面的第二个示例一样,您将默认数据库保留为空,则必须在每次运行 migrate 时提供一个数据库名称(分多次迁移数据)。 省略数据库名称将引发错误。

对于第二个例子:

python manage.py migrate --database=users
python manage.py migrate --database=customers

3. 自动数据库路由(默认路由方案)

使用多个数据库的最简单方法是建立一个数据库路由方案

默认的路由方案确保对象保持“粘性”到他们的原始数据库(即,从 xxx 数据库检索的对象将保存在同一个数据库)。 默认路由方案确保如果没有指定数据库,所有查询都返回到默认数据库

你不需要做任何事情来激活默认路由方案——它是在每个Django项目中“开箱即用”提供的。

但是,如果您想实现更强大的数据库分配行为,您可以定义自己的数据库路由器

4. 自定义路由方案(数据库路由器)

一个 database Router 是一个提供了四个方法的类:

  • db_for_read(model, **hints)

    • 应用于读取类型对象的数据库模型,如果数据库提供附加信息会在hints字典中提供,最后如果没有则返回None
  • db_for_write(model, **hints)
    • 应用于写入类型对象的数据库模型,hints字典提供附加信息,如果没有则返回None
  • allow_relation(obj1, obj2, **hints)
    • 外键操作,判断两个对象之间是否是应该允许关系,是返回True,否则返回False,如果路由允许返回None
  • allow_migrate(db, app_label, model_name=None, **hints)
    • db确定是否允许在具有别名的数据库上运行迁移操作,操作运行返回True,否则返回False,或者返回None,如果路由器没有意见。
    • app_label:位置参数是正在迁移的应用程序的标签。
    • model_name:多个迁移操作设置模型的值,如:model._meta.app_label

路由器不必提供所有这些方法——它可以省略一个或多个。 如果其中一个方法被省略,Django将在执行相关检查时跳过该路由器。

4.1 使用路由器

使用 DATABASE_ROUTERS 设置安装数据库路由器。

这个设置定义了一个类名列表,每个类名指定一个主路由器(django.db.router)使用的路由器。

主路由器用于Django的数据库操作来分配数据库的使用。 每当查询需要知道使用哪个数据库时,它就调用主路由器,提供一个模型和一个提示(如果可用的话)。 然后Django依次尝试每个路由器,直到找到数据库建议。 如果找不到提示,则尝试提示实例的当前 instance._state.db。 如果没有提供提示实例,或者 instance._state.db 为None,主路由器将分配默认数据库。

4.2 案例

4.2.1 创建数据库路由

settings.py 同级目录下创建 数据库路由器( db_router.py ),app应用会根据指定的路由选择数据库:

from .settings import DATABASE_APPS_MAPPINGDATABASE_MAPPING = DATABASE_APPS_MAPPING# 数据库路由分发
class database_router(object):def db_for_read(self, model, **hints):""""Point all read operations to the specific database.""""""将所有读操作指向特定的数据库。"""if model._meta.app_label in DATABASE_MAPPING:return DATABASE_MAPPING[model._meta.app_label]return Nonedef db_for_write(self, model, **hints):"""Point all write operations to the specific database.""""""将所有写操作指向特定的数据库。"""if model._meta.app_label in DATABASE_MAPPING:return DATABASE_MAPPING[model._meta.app_label]return Nonedef allow_relation(self, obj1, obj2, **hints):"""Allow any relation between apps that use the same database.""""""允许使用相同数据库的应用程序之间的任何关系"""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 Trueelse:return Falseelse:return Nonedef allow_syncdb(self, db, model):"""Make sure that apps only appear in the related database.""""""确保这些应用程序只出现在相关的数据库中。"""if db in DATABASE_MAPPING.values():return DATABASE_MAPPING.get(model._meta.app_label) == dbelif model._meta.app_label in DATABASE_MAPPING:return Falsereturn Nonedef allow_migrate(self, db, app_label, model=None, **hints):"""Make sure the auth app only appears in the 'auth_db' database.""""""确保身份验证应用程序只出现在“authdb”数据库中。"""if db in DATABASE_MAPPING.values():return DATABASE_MAPPING.get(app_label) == dbelif app_label in DATABASE_MAPPING:return Falsereturn None
4.2.2 settings.py 配置

setting.py 中配置 DATABASE_ROUTERS 指定自由路由文件:

# 数据库设置, xxxx0001为项目名称
DATABASE_ROUTERS = ['xxxx0001.db_router.database_router']

setting.pyDATABASE_ROUTERS 下面设置app与数据库匹配路由表,采用字典方式app名对应数据库映射名:

DATABASE_APPS_MAPPING = {'app01':'default','app02':'db2',
}
4.2.3 生成表并同步数据

分别在app01和app02下创建model类,用于生成数据表:

此处只定义了 app02 的模型,注意:加上app_label以后就会指明所属的app

from django.db import modelsclass IntelligentTableView(models.Model):table_name = models.CharField(max_length=255, verbose_name='报表名称')center = models.CharField(max_length=50, verbose_name='所属中心')on_line = models.CharField(max_length=50, verbose_name='所属线条')remake = models.CharField(max_length=255, verbose_name='备注')create_name = models.CharField(max_length=50, verbose_name='创建人')create_date = models.DateTimeField(auto_now=True, verbose_name='创建时间')is_del = models.BooleanField(default=False, verbose_name='是否删除')class Meta:db_table = 'intelligent_table'   # 表名verbose_name = '智能报表'app_label = 'app02'  # 指明app名称,用来对应app 和 数据库的map表

migrate管理命令一次只能操作一个数据库,默认操作default数据库,使用–database指定同步的数据库:

python manage.py migrate                # 生成表数据同步
python manage.py makemigrations         # # 生成迁移文件
python manage.py migrate --database=default # 同步指定数据库
python manage.py migrate --database=db2

Django——多个数据库相关推荐

  1. django引入现有数据库

    Django引入外部数据库还是比较方便的,步骤如下: 1.创建一个项目,修改seting文件,在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致. 2.运行下面代 ...

  2. Django实现对数据库数据增删改查(二)

    目录 1.基本框架 1.1.路由分发 1.2.视图函数-逻辑处理 1.3.模板 2.查询功能 2.1.视图函数 2.2.模板函数 3.添加功能 3.1.路由分发 3.2视图函数 3.3.模板 4.编辑 ...

  3. Django 笔记5 -- 数据库

    Django 笔记5 – 数据库 Django 系列笔记是笔者学习.实践使用 Django 的相关笔记,大量参考了知了课堂的<Django零基础到项目实战>教程. 参考文档: Django ...

  4. django 开发中数据库可以怎样优化

    django 开发中数据库可以怎样优化 (1)设计表时,尽量少使用外键,因为外键约束会影响插入和删除性能: (2)使用缓存,减少对数据库的访问: (3)在 orm 框架下设置表时,能用 varchar ...

  5. Django创建mysql数据库常用字段及参数

    原文衔接:https://www.cnblogs.com/yanjiayi098-001/p/11733938.html Django创建mysql数据库常用字段及参数 常用字段 1.models.A ...

  6. 关于Django中的数据库操作API之distinct去重的一个误传

    django提供的数据库操作API中的distinct()函数,了解SQL语句的读者都应该知道,DISTINCT关键字可以在select操作时去重.django里的这个distinct()函数也是这个 ...

  7. python建立文件数据库_python学习-- Django根据现有数据库,自动生成models模型文件...

    Django引入外部数据库还是比较方便的,步骤如下 : 创建一个项目,修改seting文件,在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致 运行下面代码可以自 ...

  8. django进阶06数据库事务

    原创:django进阶06数据库事务 锁 1.1:乐观锁: 概念:同一条数据很少会因为并发修改而产生冲突,适用于读多写少的场景. 实现方式:读取一个字段,执行处理逻辑,当需要更新数据时,再次检查该字段 ...

  9. Django根据现有数据库建立/更新model

    Django引入外部数据库还是比较方便的,步骤如下: 创建一个项目,修改seting文件,在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致 运行下面代码可以自动 ...

最新文章

  1. [安卓] 12、开源一个基于SurfaceView的飞行射击类小游戏
  2. 关于系统弹出错误:429 , ActiveX 部件不能创建对象 的解决方法
  3. python 学习经验 转自(http://www.elias.cn/Python/HomePage)
  4. [LeetCode]Find Minimum in Rotated Sorted Array
  5. android 隐藏输入法时自动关闭弹窗,Android监听输入法弹窗和关闭的实现方法
  6. Hibernate Criteria 条件查询
  7. APICloud可视化编程
  8. REFPROP导出温熵数据绘图
  9. 钉钉H5应用开发-jsapi调用
  10. 3COM TFTP 3CDaemon中文绿色版
  11. linux下各种player不显示mkv字幕的解决
  12. windows update 无法启动 报错87:参数错误的解决方法
  13. 光波传输的角谱理论【理论,实例及matlab代码】
  14. [转]Java实现的求解经典罗马数字和阿拉伯数字相互转换问题示例
  15. 工业级POE交换机、企业级交换机、普通交换机之间各区别?
  16. Android自定义一个属于自己的刻度尺
  17. 共享网络隐藏计算机,把电脑变成无线路由器,wifi共享大师隐藏ssid-
  18. JAVASE基础模块十五(StringBuffer类)
  19. java导出txt文件列对齐
  20. 单海军:行业AI平台赋能金融企业数智化转型

热门文章

  1. 吴恩达,确诊新冠阳性!
  2. 快手搜索技术部招聘NLP算法工程师!
  3. 卖萌屋福利场:《机器阅读理解》免费送送送!
  4. 白雪 | NLP加持知识图谱在金融事件挖掘中的应用
  5. 商汤科技-数据运维工程师-提前批笔试题目汇总
  6. 从贪心选择到探索决策:基于强化学习的多样性排序
  7. 【HTML/CSS】定位方式及区别
  8. redis笔记_源码_双端链表list
  9. Python爬虫入门四之Urllib库的高级用法
  10. javascript 学习笔记(一)