Django——多个数据库
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.py
中 DATABASE_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——多个数据库相关推荐
- django引入现有数据库
Django引入外部数据库还是比较方便的,步骤如下: 1.创建一个项目,修改seting文件,在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致. 2.运行下面代 ...
- Django实现对数据库数据增删改查(二)
目录 1.基本框架 1.1.路由分发 1.2.视图函数-逻辑处理 1.3.模板 2.查询功能 2.1.视图函数 2.2.模板函数 3.添加功能 3.1.路由分发 3.2视图函数 3.3.模板 4.编辑 ...
- Django 笔记5 -- 数据库
Django 笔记5 – 数据库 Django 系列笔记是笔者学习.实践使用 Django 的相关笔记,大量参考了知了课堂的<Django零基础到项目实战>教程. 参考文档: Django ...
- django 开发中数据库可以怎样优化
django 开发中数据库可以怎样优化 (1)设计表时,尽量少使用外键,因为外键约束会影响插入和删除性能: (2)使用缓存,减少对数据库的访问: (3)在 orm 框架下设置表时,能用 varchar ...
- Django创建mysql数据库常用字段及参数
原文衔接:https://www.cnblogs.com/yanjiayi098-001/p/11733938.html Django创建mysql数据库常用字段及参数 常用字段 1.models.A ...
- 关于Django中的数据库操作API之distinct去重的一个误传
django提供的数据库操作API中的distinct()函数,了解SQL语句的读者都应该知道,DISTINCT关键字可以在select操作时去重.django里的这个distinct()函数也是这个 ...
- python建立文件数据库_python学习-- Django根据现有数据库,自动生成models模型文件...
Django引入外部数据库还是比较方便的,步骤如下 : 创建一个项目,修改seting文件,在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致 运行下面代码可以自 ...
- django进阶06数据库事务
原创:django进阶06数据库事务 锁 1.1:乐观锁: 概念:同一条数据很少会因为并发修改而产生冲突,适用于读多写少的场景. 实现方式:读取一个字段,执行处理逻辑,当需要更新数据时,再次检查该字段 ...
- Django根据现有数据库建立/更新model
Django引入外部数据库还是比较方便的,步骤如下: 创建一个项目,修改seting文件,在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致 运行下面代码可以自动 ...
最新文章
- [安卓] 12、开源一个基于SurfaceView的飞行射击类小游戏
- 关于系统弹出错误:429 , ActiveX 部件不能创建对象 的解决方法
- python 学习经验 转自(http://www.elias.cn/Python/HomePage)
- [LeetCode]Find Minimum in Rotated Sorted Array
- android 隐藏输入法时自动关闭弹窗,Android监听输入法弹窗和关闭的实现方法
- Hibernate Criteria 条件查询
- APICloud可视化编程
- REFPROP导出温熵数据绘图
- 钉钉H5应用开发-jsapi调用
- 3COM TFTP 3CDaemon中文绿色版
- linux下各种player不显示mkv字幕的解决
- windows update 无法启动 报错87:参数错误的解决方法
- 光波传输的角谱理论【理论,实例及matlab代码】
- [转]Java实现的求解经典罗马数字和阿拉伯数字相互转换问题示例
- 工业级POE交换机、企业级交换机、普通交换机之间各区别?
- Android自定义一个属于自己的刻度尺
- 共享网络隐藏计算机,把电脑变成无线路由器,wifi共享大师隐藏ssid-
- JAVASE基础模块十五(StringBuffer类)
- java导出txt文件列对齐
- 单海军:行业AI平台赋能金融企业数智化转型