首页>>后端>>Python->django默认数据库是哪个(2023年最新整理)

django默认数据库是哪个(2023年最新整理)

时间:2023-12-12 本站 点击:0

导读:今天首席CTO笔记来给各位分享关于django默认数据库是哪个的相关内容,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

greaterwms是什么??

聚商汇WMS--开源仓库管理系统

项目介绍:

完全开源仓储管理软件,遵循Apache License 2.0协议,前后端分离,且完全开源,API使用restful协议,方便二次开发,前端代码使用quasar进行构建,后端使用Python Django3.1,利用API,可以支持多仓,波次发货,合并拣货,Milk-Run等业务模型。

软件著作权编号:2018SR517685

GitHub地址:

GitHubgithub.com/Singosgu/GreaterWMS

Demo地址:

GreaterWMS--Open Source Warehouse Management System

商务联系:mail@56yhz.com

技术交流:GreaterWMS-01(加微信进群)

项目初衷:

我在供应链行业工作了15年,发现在我们这个专业的领域,没有一款高自由度、高自定义化的软件,来深度支持我们企业的业务。大多数软件都是闭源的,而且很难去做二次开发,即使开发,周期也是非常长,开发失败的案例也是比比皆是。由于企业选择了一款软件后,其二次开发也会被开发公司绑定,至于二次开发费用,只能说呵呵。所以,我设计了这个聚商汇WMS,为的是做到一款高自由度,高自定义开发的仓库管理软件,来深度支持企业的业务。

愿景:如果你从事着非IT行业的工作,而你又热爱你的行业,那就用科技去改变他。

生命周期

V 1.0.0 -- 2019年7月 ~ 2020年12月(由于1.0.0版本的二次开发设计较为复杂,故2.0重新编写)

V 2.0.0 -- 2020年12月 ~ 2021年3月(重新编写业务逻辑,原生自带API开发文档,加入实时通信,方便企业用户互相沟通)

V 2.1.0 -- 2021年3月 ~ 2021年6月(加入了客户与企业之间的实时互动,增进企业与客户之间的业务联系,实现VMI)

V 2.2.0 -- 2020年6月 ~ 2021年9月(加入了供应商与企业之间的实时互动,增进企业与供应商之间的业务联系,实现Milk-Run和看板拉动)

V 2.3.0 -- 2021年9月 ~ 2021年12月(库存管理雏形,初步加入神经网络,深度学习库存变化)

V 3.0.0 -- 2021年12月 ~ 2022年3月(完全植入神经网络,让上下游企业可以以最低的成本运营整体的业务)

V 3.1.0 -- 2022年3月 ~ 2022年6月(区域仓库业务布局,通过深度学习,实现多仓运营,成本最低化)

开发环境:

Python 版本为 V 3.8.0 +

Django 版本为 V 3.1.0 +(该版本Django才原生支持异步实时通信)

Django-rest-framework 版本为 V 3.12.2 + (更高版本的Django-rest-Framework对Django3的兼容比较好)

Django-silk 版本为 V 4.1.0 (如果是部署上线,请关闭silk,silk仅为调试API接口速度用,有可能会泄露用户信息)

Quasar 版本为 V1.7.2 + (可以查看Quasar官网,来编辑GreaterWMS前端代码:Quasar官网)

Vue 版本为 V 2.6.0 +(尽量不要使用Vue3,因为开发环境没有使用Vue3,不知道会出现什么问题)

API,遵循 RESTful 架构

构建命令:

下载代码:

git clone

安装Python库:

pip install -r requirements.txt

注意:安装需要Twisted库,这个库有时候会安装不上,需要下载下来本地安装

下载地址:TWISTED

pip install Twisted{你下载下来的版本名称}

注意:本地安装需要注意路径

初始化数据库:

python manage.py makemigrations

迁移数据库:

python manage.py migrate

创建数据库,Django默认使用sqlite3作为数据库,如果需要mysql数据库,请在greaterwms/settings.py里面配置DATABASE

开发服务器运行:

开发运行:

daphne -p 8008 greaterwms.asgi:application

生产服务器运行:

supervisor守护进程:

pip install supervisor

使用supervisor来守护Django进程,再使用Nginx做反向代理,至于superevisor的教程有很多,这里不做讲解

Nginx支持:

推荐使用Nginx进行部署,部署的时候需要指定WebSocket链接,如果不指定,实时通信功能将报错

另需要修改axios_request.js里的ws_url

## 示例更改前

const baseurl = ''

const wsurl = 'ws://127.0.0.1:8008/'

## 示例更改后

const baseurl = 'https://你的域名/'

const wsurl = 'wss://你的域名/websocket/'

如果服务器启用了SSL,请使用https和wss,如果没有启用SSL,则使用http和ws

修改后需要重新build前端代码

开发扩展:

因为使用的前后端分离的设计,所以可以通过API,开发更多的软件应用

物流智能AGV

AGV的项目也已经开源,由于场地受限,仅实现智能发货,定点回库,使用的循迹感应器,超声波避障感应器,红外避障感应器,所有的指令通过网络传输,AGV绑定MAC地址和IP地址,保证了安全性,前提是,你需要有一个树莓派。

进销存

可以直接当一个进销存系统使用,简化仓库库位设置等操作即可。

APP和小程序

Quasar原生可以直接打包成IOS APP和Android APP

小程序的开发可以通过API开做二次开发,但小程序不支持put请求,所以需要自己再写一个请求接口。

API的组合可以达到100万种,这样我们可以根据查询请求,来获得实时报表和数据监控

供应链管理系统

产品的数量,创建时间,最后使用时间是各方面统计的,所以可以方便采购计划和调拨计划进行库存的分析

V 2.3.0及其以后的版本,将自带深度学习分析,所以可以直接使用分析结果作为供应链管理系统工具使用

多仓管理

OPENID为用户的数据唯一标识,数据组统一标识为APPID,所以很方便可以实现多仓管理

波次拣货,发货

可以设置固定时间向服务器发出请求,从而达到波次拣货的功能

也可以直接使用任务工作,通过API查询分析结果来实现,推荐使用APScheduler

~~~python pip install apscheduler ~~~

Milk-Run

V 2.2.0及其以上版本,将原生支持此功能

如果现在就需要这个业务,可以根据API调用库存消耗,来实现此功能

VMI

V 2.1.0及其以上版本,将原生支持此功能

如果现在就需要这个业务,可以根据API调用库存消耗,来实现此功能

拣货路线优化

现在的拣货路线是按照库位排序

V 2.3.0以后版本将原生支持此功能

如果现在需要这个业务,可以根据每天的拣货明细,调用API来实现此功能

开发指南:

baseurl

是发起请求的基本网址,如果是本地调试,则默认为 ,如果部署在服务器,则需要将其改为你的网站访问url

修改方式为,修改axios_request.js,注意websocket的修改之前已经提到了

Django-silk

django-silk为开发时的调试工具,可以统计每个接口的响应速度,如果需要部署到生产环境,请删除Django-silk相关配置,因为会有泄露用户信息的风险,或者直接修改Django-silk库,让用户只能看到自己的请求数据

数据库存储

数据库设计时考虑到数据迁移等问题,所以只有users里面的user_id和Django自带的user_id做了外键,其余所有字段全部没有使用外键,方便数据备份和数据库迁移

数据库是4段式设计

验证数据用户归属

验证数据安全性

验证数据是否可以存入数据库

存入数据库,并返回Response

关于数据传输

需要在所有的请求头headers里面加入token值,这个值就是用户的数据唯一标识OPENID

所有的数据传输需要设定content-type为application/json

OPENID

OPENID是注册用户数据的唯一标识,当管理员直接注册时,会有developer=1这个管理员标识。

你可以根据developer标识来做自定义二次开发

APPID

APPID是用户数据组唯一标识

如果需要多公司运营,或者多仓运营,可以通过APPID做统一链接,来实现多公司,多仓操作

用户权限

未对用户权限做过多限制,请根据自身的业务需要,做二次开发限制

业务流程:

管理员

点击注册,可以注册成为管理员账号,从而实现初始化程序设置

注册后会得到2个ID和1个开发者标识,OPENID是用户数据组唯一标识,通过OPENID绑定此OPENID下所有的数据,APPID是用户组数据唯一标识,通过APPID来实现多公司,多仓库功能,Developer标识是个布尔值,True代表这是个管理员账号

用户登入分2种:

使用OPENID和员工名称直接登入

管理员使用账号和密码登入

登入后前端会存储登入信息

可以通过查看我的OPENID来查看用户数据组的OPENID

如果需要多公司,多仓库操作,注意需要更改OPENID

更多管理员权限,请自行开发

员工管理

注册管理员后,新建一个员工

员工有2个字段,Staff_name(用于员工登入),Staff_type(员工类型来控制员工的权限)

系统没有对员工权限做任何限制,如果需要员工权限,请根据企业业务模型,自行修改Templates

点击Edit,可以修改员工信息

点击Delete,可以删除员工信息,系统后台会将Is_delete调成True

点击Contact:

可以直接和员工实时聊天,但是不可以和自己聊天

可以新建一个备忘录员工,这样做其实是当成备忘录使用

在个人中心,可以查看最近的联系人

Message标识会提醒你现在有多少未读消息

司机管理

司机管理只会在发货流程中用到

你需要知道货物是哪个司机提货取走的

仓库设置

Warehouse

仓库的创建只可以创建一个仓库,现在可以创建多个,但是只有第一个会起作用

如果需要多仓处理,可以通过APPID进行二次开发,也可以直接重新创建一个管理员账号

仓库的城市一定要填写,这是用来计算运费的

Bin_Property

库位属性决定了仓库中货物属于什么属性的货物

4种属性:破损(Damage),锁定(Holding),质检(Inspection),正常(Normal)

Beta版中,属性可以修改和删除,正式版将无法删除和修改

所有的发货,都只会匹配Normal库位的货物

收货上架和移库,都会根据库位属性,直接修改库存数量,仓库的库存数量不会出现负数

Bin_Size

库位的尺寸是帮助操作人员查看货物是否可以放入库位

现行的版本没有对上架和移库尺寸做检查,将来会加入自动检查

Bin_Set

库位设置是必须的,通常库位设置是横纵横纵,比如A010101,即A横01纵01横01纵

库位的设置需要设置库位属性和尺寸,属性很重要,他决定了此库位的货物是否为正常货物

基础设置

Company

公司基本信息的创建只可以创建一个公司,现在可以创建多个,但是只有第一个会起作用

如果需要多公司处理,可以通过APPID进行二次开发,也可以直接重新创建一个管理员账号

公司的城市一定要填写,这是用来显示在收发货单上的

Supplier

供应商的基础信息

供应商的城市一定要填写,这是用来显示在收货单上的,并且也是要自动计算运费的

Customer

客户的基础信息

客户的城市一定要填写,这是用来显示在发货单上的,并且也是要自动计算运费的

商品管理

Unit

商品的单位,系统会初始化创建一些,但可以自己添加和修改

Class

商品的类型,可以自己添加和修改

Color

商品的颜色,系统会初始化创建一些,但可以自己添加和修改

Brand

商品的品牌,可以自己添加和修改

Shape

商品的形状,系统会初始化创建一些,但可以自己添加和修改

Specs

商品的规格,可以自己添加和修改

Origin

商品的产地,可以自己添加和修改

Goods List

商品的列表

固定资产

Capital

固定资产创建,没有做过多拓展,只是记录使用

可以统计托盘账目等

库存管理

Stock List

在库的货物总的库存数据量

Onhand_stock现有的库存数量

Can Order,可以用于下单发货的库存数量,因为有些货物已经被下了订单,虽然有现有库存,但是不可以再被订货

Ordered Stock,已经被下单的货物数量

ASN Stock,已经下了到货通知书,但还没有确认到货通知书的货物数量

DN Stock,已被下单,但是还没有确认订单数量

Pre Load,预计到货货物数量

Pre Sort,已经到货,卸货完成,等待分拣的货物数量

Sorted Stock,货物分拣完成,等待上架的货物数量

Pick Stock,发货单生成了拣货单,等待拣货的货物数量

Picked Stock,已经拣货完成,等待和司机交接的货物数量

Back Order Stock,欠货订单数量

Bin Stock

Total Stock,这个库位该产品的所有库存数量

Pick Stock,这个库位需要拣货的数量

Picked Stock,这个库位拣货完成的数量

Move To Bin, 移库,移库后,会根据库位属性,直接更新库存数量,如果库位全部移空,则该库位会更新为空库位

Empty Bin

空库位明细

Occupied Bin

非空库位明细

收货管理

ASN到货通知书状态

ASN Status = 1, ASN到货通知书创建完成,状态1是唯一可以删除和修改ASN信息的状态,他会显示在Pre Delivery中,即有了到货通知书,但是还没有到货,点击Confirm Delivery,即确认货物已经到达,ASN Status更新到2,此时已经无法再修改ASN信息

ASN Status = 2, 拓展开发为司机到货排队,如果我们有很多司机到货,这可以做成一个排队系统,同时也可以让采购和销售看到到货信息,减少不必要的邮件和电话沟通,点击Finish Loading,即确认货物已经卸货完成,ASN Status更新到3,货物信息会出现在Sorting,此时的ASN状态表示,货物已卸到仓库,等待分拣

ASN Status = 3, 货物分拣是必须的一个流程,没有货物分拣,货物是无法上架的,上架的原则就是货物整理好,摆放到相对应的库位上,点击Confirm Sorted,ASN Status更新到4,即确认分拣完成,等待上架

此时移动Sorted页面,会出现需要上架的货物明细,点击Move To Bin,上架完成,当然,系统会根据上架后的库位属性,自动更新商品库存数量信息

发货管理

DN发货单状态

DN Status = 1, DN发货单创建完成,此时订单还是可以修改状态,且系统中的库存数量不会发生任何改变,点击Confirm Order,DN Status更新到2,即订单已经被确认,且无法更改,同时系统中的货物库存数量会自动更新,比如Can Order数量和Ordered数量

DN Status = 2, 这是订单被确认等待生成拣货单的过程,你可以点击单条订单Order Release来生成一个订单的拣货单,你也可以点击Release All Order,来将所有订单生成拣货单,如果是所有订单Release,那么会根据时间的先后进行库存匹配,库存不足时,会生成Back Order,即欠货订单,在这个过程中,DN单号是会发生改变的,如一家客户的多张订单,会被统一到一张订单中进行拣货,如客户订单无法满足,会将未满足部分生成欠货订单,欠货订单如果仍未得到匹配库存满足,将不再生成新的订单,DN Status会更新到3,即等待拣货的过程,已确认的订单和欠货订单都时Status为2的状态

DN Status = 3, 直接拣货,此功能会出现在Beta5更新中,暂时未更新

DN Status = 4, 发货交接,此功能会出现在Beta6更新中,暂时未更新

DN Status = 5, 客户签收,此功能会出现在Beta7更新中,暂时未更新

DN Status = 6, 对账结束,订单关闭,此功能会出现在Beta7更新中,暂时未更新

退货管理

RO退货订单 此功能将会出现在正式版中

运费管理

Transportation Fee API已经完成,前端暂未更新入口,如果想要使用,可以直接调用Payment下的Transportation Fee API进行使用,运费自动计算模块已经做进收发货流程中

django支持哪些数据库

常见的关系数据库postgresql、mysql、oracle、sqlite这些都支持,官方优先推荐PostgreSQL关系数据库。

除上面之外还支持以下数据源:

SAP SQL Anywhere

IBM DB2

Microsoft SQL Server

Firebird

ODBC

django开发用什么数据库好

使用多个数据库

New in Django 1.2: Please, see the release notes

大多数其他文档都假设使用单一数据库,本文主要讨论如何在 Django 中使用多个数据库。 使用多个数据库,要增加一些步骤。

定义你的数据库

使用多数据库的第一步是通过 DATABASES 设置要使用的数据库服务。这个 设置用于映射数据库别名和特定的联结设置字典,这是 Django 定义数据库一贯的手法。 字典内部的设置参见 DATABASES 文档。

数据库可以使用任何别名,但是 default 有特殊意义。当没有选择其他数据库时, Django 总是使用别名为 default 的数据库。因此,如果你没有定义一个名为 default 的数据库时,你应当小心了,在使用数据库前要指定你想用的数据库。

以下是一个定义两个数据库的 settings.py 代码片断。定义了一个缺省的 PostgreSQL 数据库和一个名为 users 的 MySQL 数据库:

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

如果你尝试访问 DATABASES 设置中没有定义的数据库, Django 会抛出一个 django.db.utils.ConnectionDoesNotExist异常。

同步你的数据库

syncdb 管理命令一次只操作一个数据库。缺省情况下,它操作 default 数据库。但是加上 --database 参数,你可以让 syncdb 同步不同的 数据库。所以要同步我们例子中的所有数据库的所有模型可以使用如下命令:

$ ./manage.py syncdb

$ ./manage.py syncdb --database=users

如果你不是同步所有的程序到同一个数据库中,你可定义一个 数据库路由 来为指定的模型实施特定的控制 策略。

如果你要精细地控制同步,那么还有一种方式是修改 sqlall 的输出,手工在 数据库中执行命令,命令如下:

$ ./manage.py sqlall sales | ./manage.py dbshell

使用其他管理命令

其他操作数据库的 django-admin.py 命令与 syncdb 类似,他们一次只 操作一个数据库,使用 --database 来控制使用哪个数据库。

自动数据库路由

使用多数据库最简单的方法是设置一个数据库路由方案。缺省的路由方案确保对象 “紧贴”其原本的数据库(例如:一个对象从哪个数据库取得,就保存回哪个数据库)。 缺省的路由方案还确保如果一个数据库没有指定,所有的查询都会作用于 缺省 数据 库。

你不必为启动缺省路由方案作任何事,因为它是“开箱即用”的。但是,如果你要执行 一些更有趣的数据库分配行为的话,你可以定义并安装你自己的数据库路由。

数据库路由

一个数据库路由是一个类,这个类最多有四个方法:

db_for_read(model, **hints)

建议 model 对象写操作时使用的数据库。

如果一个数据库操作可以提供对选择数据库有用的附加信息,那么可以通过 hints 字典提供。详见 下文 。

如果没有建议则返回 None 。

db_for_write(model, **hints)

建议 model 对象读操作时使用的数据库。

如果一个数据库操作可以提供对选择数据库有用的附加信息,那么可以通过 hints 字典提供。详见 下文 。

如果没有建议则返回 None 。

allow_relation(obj1, obj2, **hints)

当 obj1 和 obj2 之间允许有关系时返回 True ,不允许时返回 False ,或者没有 意见时返回 None 。这是一个纯粹的验证操作,用于外键和多对多操作中,两个对象 的关系是否被允许。

allow_syncdb(db, model)

决定 model 是否可以和 db 为别名的数据库同步。如果可以返回 True , 如果不可以返回 False ,或者没有意见时返回 None 。这个方法用于决定一个给定 数据库的模型是否可用。

一个路由不必提供 所有 这些方法,可以省略其中一个或多个。如果其中一个方法被 省略了,那么 Django 会在执行相关检查时跳过相应路由。

提示参数

数据库路由接收的“提示”参数可用于决定哪个数据库应当接收一个给定的请求。

目前,唯一可以提供的提示参数是 实例 ,即一个与读写操作相关的对象的实例。 可以是一个已保存的对象的实例,也可以是一个多对多关系中添加的实例。在某些情况下, 也可能没有对象的实例可以提供。路由会检查提示实例是否存在,并相应地决定是否改变 路由行为。

使用路由

数据库路由使用 DATABASE_ROUTERS 设置来安装。这个设置定义一个类名称 列表,每个类定义一个用于主路由 (django.db.router) 的路由。

主路由用于 Django 分配数据库操作。当一个查询想要知道使用哪个数据库时,会提供 一个模型和一个提示(如果有的话),并调用主路由。

Django 就会按次序尝试每个路由,

直到找到合适的路由建议。如果找不到路由建议就会尝试实例提示的当前的 _state.db 。如果没有提供路由提示,或者实例没有当前数据库状态,那么

主路由会 分配 缺省 数据库。

一个例子

仅用于示例目的!

这个例子仅用于展示路由如何改变数据库的使用。本例有意忽略了一些复杂的东西以 便于更好的展示路由是如何工作的。

如果任何一个 myapp 中的模型包含与 另一个 数据库中模型的关系时,本例 是无效的。参见 跨数据库关系一节中介绍 的 Django 引用完整性问题。

本例的主/从配置也是有缺陷的:它没有处理复制延时(比如因为把写操作传递给从 数据库耗费时间而产生的查询不一致),也没有考虑与数据库使用策略的交互作用。

那么,这个例子有什么用呢?本例仅用于演示一个 myapp 存在于 other 数据库, 所有其他模型之间是主/从关系,且存在于 master 、 slave1 和 slave2 数据库。本例使用了两个路由:

class MyAppRouter(object): """ 一个控制 myapp 应用中模型的 所有数据库操作的路由 """ def db_for_read(self, model, **hints): "myapp 应用中模型的操作指向 'other'" if model._meta.app_label == 'myapp': return 'other' return None def db_for_write(self, model, **hints): "myapp 应用中模型的操作指向 'other'" if model._meta.app_label == 'myapp': return 'other' return None def allow_relation(self, obj1, obj2, **hints): " 如果包含 myapp 应用中的模型则允许所有关系 " if obj1._meta.app_label == 'myapp' or obj2._meta.app_label == 'myapp': return True return None def allow_syncdb(self, db, model): " 确保 myapp 应用只存在于 'other' 数据库 " if db == 'other': return model._meta.app_label == 'myapp' elif model._meta.app_label == 'myapp': return False return None class MasterSlaveRouter(object): """ 一个设置简单主/从定义 的路由 """ def db_for_read(self, model, **hints): " 所有读操作指向一个随机的从数据库 " return random.choice(['slave1','slave2']) def db_for_write(self, model, **hints): " 所有写操作指向主数据库 " return 'master' def allow_relation(self, obj1, obj2, **hints): " 允许数据库池中的两个对象间的任何关系 " db_list = ('master','slave1','slave2') if obj1._state.db in db_list and obj2._state.db in db_list: return True return None def allow_syncdb(self, db, model): " 显示地放置所有数据库中的模型 " return True

然后在你的设置文件增加如下内容(把 path.to. 替换为你定义路由的模型的路径 ):

DATABASE_ROUTERS = ['path.to.MyAppRouter', 'path.to.MasterSlaveRouter']

这个设置中,路由的顺序是很重要的,因为查询时是按这个设置中的顺序依次查询的。上 例中, MyAppRouter 先于MasterSlaveRouter ,因此, myapp 中的模型就 优先于其他模型。如果 DATABASE_ROUTERS 设置中两个路由的顺序变换了, 那么 MasterSlaveRouter.allow_syncdb() 会优先执行。因为 MasterSlaveRouter 是 包罗万象的,这样就会导致所有模型可以使用所有数据库。

设置好之后让我们来运行一些代码:

# 从 'credentials' 数据库获得数据 fred = User.objects.get(username='fred') fred.first_name = 'Frederick' # 保存到 'credentials' 数据库 fred.save() # 随机从从数据库获得数据 dna = Person.objects.get(name='Douglas Adams') # 新对象创建时还没有分配数据库 mh = Book(title='Mostly Harmless') # 这个赋值会向路由发出请求,并把 mh 的数据库设置为与 author 对象同样的 # 数据库 mh.author = dna # 这会强制 'mh' 实例使用主数据库... mh.save() # ... 但如果我们重新获取对象,就会从从数据库中获取 mh = Book.objects.get(title='Mostly Harmless')

手动选择数据库

Django 也提供一个可以让你通过代码完全控制数据库使用的 API 。手动定义数据库分配 优先于路由。

为一个 查询集 手动选择一个数据库

你可以在 查询集 “链”中的任何点为 查询集 选择数据库。我们通过在 查询集 上调用 using() 来得到使用指定数据库的另一个 查询集 。

using() 使用一个参数:你想要运行查询的数据库的别名。例如:

# 这会运行在“缺省”数据库上。 Author.objects.all() # 这同样会运行在“缺省”数据库上。 Author.objects.using('default').all() # 这会运行在“ other ”数据库上。 Author.objects.using('other').all()

为 save() 选择一个数据库

在使用 Model.save() 时加上 using 关键字可以指定保存到哪个数据库。

例如,要把一个对象保存到 legacy_users 数据库应该这样做:

my_object.save(using='legacy_users')

如果你不定义 using ,那么 save() 方法会根据路由分配把数据保存到缺省 数据库中。

把一个对象从一个数据库移动到另一个数据库

当你已经在一个数据库中保存了一个对象后,你可能会使用 save(using=...) 把这个 对象移动到另一个数据库中。但是,如果你没有使用恰当的方法,那么可能会出现意想不 到的后果。

假设有如下的例子:

p = Person(name='Fred') p.save(using='first') # (第一句) p.save(using='second') # (第二名)

在第一名中,一个新的 Person 对象被保存到 first 数据库中。这时, p 还没有一个主键,因此 Django 执行了一个INSERT SQL 语句。这样就会创建一个 主键,并将这个主键分配给 p 。

在第二句中,因为 p 已经有了一个主键,所以 Django 在保存对象时会尝试在新的 数据库中使用这个主键。如果 second数据库中没有使用这个主键,那就不会有问题, 该对象会复制到新数据库。

然而,如果 p 的主键在 second 数据库中已经使用过了,那么 second 使用 这个主键的已存在的对象将会被 p 覆盖。

有两种方法可以避免上述情况的发生。第一,你可以清除实例的主键。如果一个对象没有 主主键,那么 Django 会把它看作一个新对象,在保存到 second 数据库中时就不会 带来数据的损失:

p = Person(name='Fred') p.save(using='first') p.pk = None # 清除主键。 p.save(using='second') # 写入一个全新的对象。

第二种方法是在 save() 方法中使用 force_insert 选项来保证 Django 执行 一个 INSERT SQL:

p = Person(name='Fred') p.save(using='first') p.save(using='second', force_insert=True)

这样可以保证名为 Fred 的人员在两个数据库中使用相同的主键。如果在保存到 second 数据库时主键已被占用,会抛出一个错误。

选择一个要删除数据的数据库

缺省情况下,一个现存对象从哪个数据库得到,删除这个对象也会在这个数据库中进行:

u = User.objects.using('legacy_users').get(username='fred') u.delete() # 会从 `legacy_users` 数据库中删除

通过向 Model.delete() 方法传递 using 关键字参数可以定义在哪个数据库中删除 数据。 using 的用法与 save() 方法中使用这个参数类似。

例如,假设我们要把一个用户从 legacy_users 数据库移动到 new_users 数据库 可以使用如下命令:

user_obj.save(using='new_users') user_obj.delete(using='legacy_users')

多数据库情况下使用管理器

在管理器上使用 db_manager() ,可以让管理器访问一个非缺省数据库。

例如,假设你有一个操作数据库的自定义管理器 User.objects.create_user() 。

因为 create_user() 是一个管理器方法,不是一个 查询集 ,所以你不能

用 User.objects.using('new_users').create_user() 。( create_user() 方法

只能用于 User.objects 管理器,而不能用于,管理器衍生出的 查询集 。) 解决方法是使用 db_manager() ,就象下面这样:

User.objects.db_manager('new_users').create_user(...)

db_manager() 返回的是绑定到你指定的数据库的管理器的一个副本。

多数据库情况下使用 get_query_set()

如果你在管理器中重载了 get_query_set() ,请确保在其父类中也调用了相同的方法 (使用 super() )或者正确处理管理器中的 _db 属性(一个包含要使用的数据库 名称的字符串)。

例如,如果你要从 get_query_set 方法返回一个自定义 查询集 类,那么你可以 这样做:

class MyManager(models.Manager): def get_query_set(self): qs = CustomQuerySet(self.model) if self._db is not None: qs = qs.using(self._db) return qs

在 Django 管理接口中使用多数据库

Django 的管理接口没有明显支持多数据库。如果想要支持的话你必须写自定义 ModelAdmin 。

如果要支持多数据库,那么 ModelAdmin 对象有五个方法要自定义:

class MultiDBModelAdmin(admin.ModelAdmin): # 为方便起见定义一个数据库名称常量。 using = 'other' def save_model(self, request, obj, form, change): # 让 Django 保存对象到 'other' 数据库。 obj.save(using=self.using) def delete_model(self, request, obj): # 让 Django 从 'other' 数据库中删除对象。 obj.delete(using=self.using) def queryset(self, request): # 让 Django 在 'other' 数据库中搜索对象。 return super(MultiDBModelAdmin, self).queryset(request).using(self.using) def formfield_for_foreignkey(self, db_field, request=None, **kwargs): # 让 Django 基于 'other' 数据库生成外键控件。 return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs) def formfield_for_manytomany(self, db_field, request=None, **kwargs): # 让 Django 基于 'other' 数据库生成多对多关系控件。 return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)

结语:以上就是首席CTO笔记为大家介绍的关于django默认数据库是哪个的全部内容了,希望对大家有所帮助,如果你还想了解更多这方面的信息,记得收藏关注本站。


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