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.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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491858.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聚焦第三届世界智能大会|大佬们讲了哪些干货?

文章来源:天津广播今天第三届世界智能大会举办两场主论坛高峰会柳传志、周鸿祎、王传福等各界大咖悉数亮相嘉宾围绕智能科技产业发展进行深层次探讨展开深度思想碰撞分享创新经验演讲的干货信息都在这了 ▼万钢:人工智能遇到“成长的烦恼”全国政协副主席…

tf.nn.embedding_lookup

用法: a1 tf.nn.embedding_lookup(a, index) index是索引,a是输入,通过index来选取a中对应的元素返回给a1,注意index是从0开始算起 例子: import tensorflow as tfa tf.constant([5, 6, 7, 8, 9]) index tf.con…

mac下配置eclipse的maven环境

转自:http://www.cnblogs.com/yqskj/archive/2013/03/30/2990292.html 1、下载maven的bin包,解压,配置到环境变量里面去 1)、首先到Maven官网下载安装文件,比如 ,下载文件为apache-maven-3.0.3-bin.tar.gz2…

装饰器详解

装饰器 1. 需求 需求:在func函数执行前输出before,执行后输出after。 def func():print("我是func函数")value [11,22,33,44]return valueresult func() print(result)1.1 闭包实现 # ********闭包实现******** def func():print("…

tf.sequence_mask

用法: sequence_mask(lengths,maxlenNone,dtypetf.bool,nameNone ) 函数参数 lengths:整数张量,其所有值小于等于maxlen。maxlen:标量整数张量,返回张量的最后维度的大小;默认值是lengths中的最大值。dt…

国产首款脑机编解码集成芯片发布

来源:科学网5月17日,由中电云脑(天津)科技有限公司(简称“中电云脑”)联合天津大学共同研发的国产首款脑机编解码集成芯片——“脑语者”在天津第三届世界智能大会上正式发布。这是一款拥有完全自主知识产权…

软件工程的认识

软件工程是一门研究用工程法构建和维护有效的、实用的和高品质的软件的学科。它涉及程序设计语言、数据库、软件开发工具、系统平台、标准、设计模式方面。在现代社会中,软件应用于多个方面。典型的软件有电子邮件、嵌入式系统、人机界面、办公套件、操作系统、编译…

tf.while_loop

用法: final_state tf.while_loop(cond, loop_body, init_state) cond 是一个函数,负责判断继续执行循环的条件。loop_body 是每个循环体内执行的操作,负责对循环状态迸行更新。init_state 为循环的起始状态,它可以包含多个 T…

mysql 8.0.25 取巧解决修改密码报错问题

mysql修改密码 报错 # 修改密码 set password for rootlocalhostpassword(新密码);1.1 报错: ERROR 1064 (42000): You have an error in your SQL syntax;check the manual that corresponds to your MySQL server version for the right syntax to use near pas…

资金只够支撑10个月,自动驾驶致命事故重演:特斯拉陷入困境

来源:机器学习研究会订阅号特斯拉在上海的工厂正在快速建设过程中,然而最近马斯克的一封致员工信引发了人们对于这家车企的担忧。另一方面,同日曝光的 Model 3 自动驾驶致命事故又为新技术的前途蒙上了阴影。据路透社、Electrek 等媒体报道&a…

把WinRAR默认压缩格式换为ZIP

使用WinRAR的一个技巧,说实话,我并不喜欢WinRAR,不过不可否认这个软件有其方便的地方,在一些细节方面7Zip的确不如WinRAR做的好。 例如,WinRAR默认建立的压缩包都是RAR格式的,但我们希望默认都使用ZIP格式的…

颠覆性技术的兴起及其影响

来源:学习时报1990年代美国学者克里斯滕森提出“颠覆性技术”之后,这一“时髦”的概念经常出现在商业、军事等不同的学科和领域,对国家竞争力、经济、安全、国家关系等方面产生了深远影响。许多国家和地区都充分意识到了这一问题的重要性&…

tf.concat()

tf.concat(values,axis, nameconcat ) 作用: 在axis维度上对输入矩阵进行拼接 例子: import tensorflow as tfa tf.constant([[1, 2, 3], [4, 5, 6]]) b tf.constant([[7, 8, 9], [10, 11, 12]]) c tf.concat([a, b], axis0) d tf.concat([a, b]…

Windows Redis安装

Windows Redis安装 在 Windows 系统下安装 Redis 要比 Linux 系统安装稍微复杂一些。 下载地址:点击前往 解压文件,目录如下: 2.1 启动服务端程序 如上图所示,双击 Redis 服务端启动程序 redis-server.exe,看到以下…

Android Studio如何快速生成get,set,tostring,构造函数

刚开始使用Android Studio时,在创建一个javabean时,很习惯的在JavaBean类中,右键去找生成get,set等选项。但是很遗憾,找不到。 那这边如何快速的set,get或者生成构造函数,生成toString方法。 有…

python面试-2

python中的数据类类型 Python3 中有六个标准的数据类型: Number(数字)String(字符串)List(列表)Tuple(元组)Set(集合)Dictionary(字…

科幻变成现实?超导加速未来新科技

来源:未来产业促进会演绎inSite 第十二期节目超导:改变未来世界罗会仟,中国科学院物理研究所副研究员、科普作家、中国科学院青年创新促进会数理分会会长。获首届全国青年科学博客大赛 “最佳科学博客奖”、中国科普作家协会优秀科普作品金奖…

[转载]用UglifyJS2合并压缩混淆JS代码——javascript系列

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架…

tf.logging.set_verbosity (tf.logging.INFO)

tf.logging.set_verbosity (tf.logging.INFO) 作用&#xff1a;将 TensorFlow 日志信息输出到屏幕 TensorFlow有五个不同级别的日志信息。其严重性为调试DEBUG<信息INFO<警告WARN<错误ERROR<致命FATAL。当你配置日志记录在任何级别&#xff0c;TensorFlow将输出…

为什么说无人出租车关乎特斯拉和Uber的生死存亡

来源 网易智能在英特尔高级副总裁兼Mobileye首席执行官阿姆农沙舒亚&#xff08;Amnon Shashua&#xff09;看来&#xff0c;对于特斯拉、Uber和Lyft来说&#xff0c;无人驾驶出租车市场之争关乎生死存亡。如果你必须要听一个打车公司的高管说说随着无人驾驶出租车的兴起&#…