django外键和多数据库应用
为什么80%的码农都做不了架构师?>>>
模型中如果有外键和多对多字段,创建的时候外键必须首先绑定,然后保存,才能添加多对多字段。
from django.db import models class User(models.Model): name = models.CharField(max_length=30) class Group(models.Model): name = models.CharField(max_length=30) owner = models.ForeignKey(User) member = models.ManyToMany(User)from models import User,Group #第一种创建对象的方法必须调用save()函数,否则不会真正向数据库写入 u1 = User() u1.name = 'ZhangSan' u1.save() #一次创建并写入数据库,与上面的等价 u2 = User.objects.create(name='LiSi') g = Group() g.name = "My group" g.owner = u1 g.save() #必须调用save函数写入数据库后才能添加多对多,否则Group对象在数据库中没有对应primary_key无法建立关联 g.member.add(u2)
多应用和多数据库 --- 转载自他人
前一段在学习过程中,想的都比较简单,所以就只有一个应用一个数据库,但是当写的东西多了就发觉不同功能应该由不同应用来处理,不同应用可以使用单独使用自己的数据库,这样比较利于网站的扩展。原谅我,比较懒,所以废话就少说吧。
首先,假定项目名为test,有两个应用,user用于管理用户,essay用于管理文章。
python manage.py startapp userApp
python manage.py startapp essayApp
#userApp的models.py中
from django.db import models
class User(models.Model):
name = models.CharField(max_length=30)
#essayApp中的models.py中
from django.db import models
from userApp.models import User
class Essay(models.Model):owner = models.ForeignKey(User,related_name="essay_owner")content = models.TextField()
在settings.py中为两个应用注册
INSTALLED_APPS = (#原来系统默认存在的我就略去不说了……'userApp','essayApp',)
添加将要使用的数据库
DATABASES = {#之所以这里仍然保留default数据库,是因为如果要使用Django的Auth应用或者Admin应用#我希望它默认将数据存放在default.db中,而不与其他数据搞混,当然也可以额外指定,后边会说
'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': 'db/default.db','USER': '','PASSWORD': '','HOST': '','PORT': '',},#提供给userApp使用
'userdb': {'ENGINE': 'django.db.backends.sqlite3','NAME': 'db/user.db','USER': '','PASSWORD': '','HOST': '','PORT': '',},
#提供给essayApp使用'essaydb': {'ENGINE': 'django.db.backends.sqlite3','NAME': 'db/essay.db','USER': '','PASSWORD': '','HOST': '','PORT': '',},
}
就目前工作来说,还没完成,如果执行python manage.py syncdb 则会看到userApp_User和essayApp_Essay两张表都建在了default.db中,因为我们虽然添加了两个数据库配置,但是还没指定哪一个应用使用哪一个数据库,因此都使用了默认数据库配置 ‘default’
新建一个dbsetings.py
class appdb(object):
02
03 def db_for_read(self, model, **hints):
04 #该方法定义读取时从哪一个数据库读取
05 return self.__app_router(model)
06
07 def db_for_write(self, model, **hints):
08 #该方法定义写入时从哪一个数据库读取,如果读写分离,可再额外配置
09 return self.__app_router(model)
10
11 def allow_relation(self, obj1, obj2, **hints):
12 #该方法用于判断传入的obj1和obj2是否允许关联,可用于多对多以及外键
13 #同一个应用同一个数据库
14 if obj1._meta.app_label == obj2._meta.app_label:
15 return True
16 #User和Essay是允许关联的
17 elif obj1._meta.app_label in ('userApp','essayApp') and
18 #接上一行 obj2._meta.app_label in ('userApp','essayApp'):
19 return True
20
21
22 def allow_syncdb(self, db, model):
23 #该方法定义数据库是否能和名为db的数据库同步
24 return self.__app_router(model) == db
25
26 #添加一个私有方法用来判断模型属于哪个应用,并返回应该使用的数据库
27 def __app_router(self, model):
28 if model._meta.app_label == 'userApp':
29 return 'userdb'
30 elif model._meta.app_label == 'essayApp':
31 return 'essaydb'
32 else :
33 return 'default'
在settings.py中添加数据库配置文件
DATABASE_ROUTERS = ['dbsettings.appdb']
至此,工作基本完毕。
但是要注意的是必须单独为每一个数据库同步,即
python manage.py syncdb #默认同步的数据库为'default'
python manage.py syncdb --database=userdb #为userdb同步数据
python manage.py syncdb --database=essaydb #为essaydb同步数据
昨天本以为实现了不同数据库之间多对多的查询,外键可以正常访问,多对多今天研究半天都没有成功,查询Django官方文档,发现明确写着
Django目前不提供外键或多对多的关系跨越多个数据库的支持。如果你使用路由器分割模型对不同的数据库,任何FOREIGNKEY和多对多关系的模型定义必须是单个数据库的内部。
然而,如果你使用SQLite或MySQL,MyISAM,没有强制引用完整性;作为结果,你可以'假'跨数据库外键。然而,这样的配置是不由Django官方支持。
原来我渣一般的爬文水平,以上引用是机械翻译过来的……
https://docs.djangoproject.com/en/1.4/topics/db/multi-db/
但是存在的一点问题,就是当一个应用的模型多对多关联到另一个应用的模型(两个应用使用不同数据库)时,相互之间的查询就会出一些问题。
以昨天文章为基础,作如下修改
1
|
#userApp的models.py中
|
2
|
from django.db import models
|
3
|
class User(models.Model):
|
4
|
name = models.CharField(max_length = 30 )
|
1
|
#essayApp中的models.py中
|
2
|
from django.db import models
|
3
|
from userApp.models import User
|
4
|
class Essay(models.Model):
|
5
|
#owner = models.ForeignKey(User,related_name="essay_owner")
|
6
|
#我们假设一篇文章可以有多个作者
|
7
|
owner = models.ManyToManyField(User,related_name = "essay_owner" )
|
8
|
content = models.TextField()
|
同时,在dbsettings.py中指明两个应用可以关联,虽然上一篇文章有提到,但还是再次说明一下,即:
1
|
def allow_relation( self , obj1, obj2, * * hints):
|
2
|
#该方法用于判断传入的obj1和obj2是否允许关联,可用于多对多以及外键
|
3
|
#同一个应用同一个数据库
|
4
|
if obj1._meta.app_label = = obj2._meta.app_label:
|
5
|
return True
|
6
|
#User和Essay是允许关联的
|
7
|
elif obj1._meta.app_label in ( 'userApp' , 'essayApp' ) and
|
8
|
#接上一行 obj2._meta.app_label in ('userApp','essayApp'):
|
9
|
return True
|
我们再次假设,u1是一个User对象,e1是一个Essay对象,并且已经调用e1.owner.add(u1)添加关联。(原谅我比较懒再重新在shell里边写贴上来)
在view中如果使用u1.essay_owner.all()逆向查询就会报错,因为essayApp_essay_owner这个表不存在于userApp所使用的数据库'userdb'中,此时需要指定所使用的数据库,即u1.essay_owner.using('essaydb').all()
令人疑惑的是,如果使用e1.owner.all()进行查询,也会报错,原因是userApp_user这个表不存在于'essaydb'这个数据库中,但是当使用e1.owner.using('userdb').all()时,也会报错,原因是essayApp_essay_owner这个表不存在于'userdb'中,这就比较蛋疼了。Django官方文档中明确指出官方目前不支持跨数据库使用多对多关系和外键。
因此,如果要实现跨数据库使用多对多,就要靠自己实现,我试了很多方法均失败,昨天想到一个方法是自己链接两个数据库并写相应的SQL语句来查询,但是这样就比较麻烦,而且到时候改变使用其他数据库也要重新写相应的SQL语句。
经过今天测试,好在外键还是能正常使用,所以想了一个办法来实现跨数据库的多对多关系。
这里,再次对essayApp的models.py进行更改
01
|
#essayApp中的models.py中
|
02
|
from django.db import models
|
03
|
from userApp.models import User
|
04
|
class Essay(models.Model):
|
05
|
#owner = models.ForeignKey(User,related_name="essay_owner")
|
06
|
#我们假设一篇文章可以有多个作者
|
07
|
#owner = models.ManyToManyField(User,related_name="essay_owner")
|
08
|
09
|
#通过使用through来指定一张表定义User与Essay之间的关系
|
10
|
#PS:经过后来测试,发现如果有多个多对多指向User,这里related_name这个参数还是少不了的
|
11
|
owner = models.ManyToManyField(User,related_name = "essay_owner" ,through = "ownerRelation" )
|
12
|
content = models.TextField()
|
13
|
14
|
class ownerRelation(models.Model):
|
15
|
#需要指出,使用through参数指定关系,在ownerRelation中,必须包含至少两个外键
|
16
|
#分别指向User与Essay
|
17
|
user = ForeignKey(User,related_name = "ownerRelation_owner" )
|
18
|
essay = ForeignKey(Essay,related_name = "ownerRelation_essay" )
|
此时创建一个关系对象
1
|
o1 = ownerRelation.objects.create(user = u1,essay = e1)
|
在view中通过
1
|
o1 = u1.ownerRelation_owner.using( 'essaydb' ). all ()[ 0 ] #为方便说明直接使用第一个对象
|
逆向查询就可以获得这个ownerRelation对象,此时使用
o1.essay即可获得对应的essay,反过来用e1来查询也是如此
1
|
o1 = e1.ownerRelation_essay. all ()[ 0 ] #这里不需要额外指定使用的数据库
|
2
|
o1.user即可获得对应的user
|
e1这篇文章所有的owner,即
1
|
O = e1.ownerRelation_essay. all ()
|
2
|
for o in O:
|
3
|
o.user
|
4
|
#……
|
需要指出的是,e1.owner.all()等一系列查询方法均不可用,因为多对多关联的模型不在同一数据库,如果是同一数据库,仍是可用的,另外,add和remove等方法被系统禁用,原因是使用了ownerRelation这样的表来指定多对多之间的关系,但是add方法并不能自动为你创建相应的ownerRelation对象。不过使用这种方法也不是没有好处的,使用through,能够使关系更加明了,并且你可以在关系模型中添加一些其他的属性,比如一个date = models.DateField(auto_now_add=True),可以记录关系建立的日期等
笔记到此,虽然仍然麻烦了一点。
希望有其他方法的朋友请不要吝惜,分享给我!
同时,这个方法目前来说没发现有什么bug,但是由于官方本来就不提供跨数据库的多对多支持,因此可能存在潜在问题,不过也得遇到了才能说。
转载于:https://my.oschina.net/shniu/blog/223677
django外键和多数据库应用相关推荐
- mysql 外键查询_mysql 外键查询(mysql数据库多表联查)
mysql 外键查询(mysql数据库多表联查) 2020-07-24 11:51:00 共10个回答 查看方式主要是通过第三方工具或者是sql语句,主要有以下三种方式1:使用Navicateform ...
- django外键-left join
创建model模型 from django.db import modelsclass Category(models.Model):name = models.CharField(max_lengt ...
- mysql数据库如何添加外键约束_MySQL数据库之外键约束的简单理解
定义 如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键.由此可见,外键表示了两个关系之间的相关联系.以另一个关系的外键作主关键字的表被称为主表,具有此外键的表被称为主表的 ...
- 查看外键名称查看数据库外键名字
我们要进行删除外键时,需要知道外键的名字,那么如何查看数据库外键呢?有2种方式查看: 1.过查看表的方式查看外键名字: 2.通过mysql自带的系统表查看外键. 更多精彩请访问本文源地址: https ...
- mysql一对一外键约束_MySQL数据库之-foreign key 外键(一对多、多对多、一对一)、修改表、复制表...
我们在同一数据库创建的表时候,很多时候会出现相同数据的冗余问题,也就是说几个id会有一个或者同n个相同字段,这样就导致数据表结构数据重复冗余, 冗余还无所谓,关键是如果我要改其中一个相同的字段信息,其 ...
- mysql主键和外键示例_SQL数据库中主键和外键的应用实例
数据库 什么是数据库主键(Primary Key)? 数据库主键(Primary Key):指的是一个列或多列的属性组合,其属性值能唯一标识一条记录,通过它可强制表的实体完整性. 例如: (tb_Bo ...
- django外键获取数据
用django写一个项目时,使用外键获取数据遇到一个问题. models创建的购物车表: class CarModel(models.Model):user = models.ForeignKey(U ...
- Django外键约束
ORM外键约束 from django.db import models# 出版社 class Publisher(models.Model):id = models.AutoField(primar ...
- wamp mysql外键设置_数据库外键是什么意思
数据库外键是什么意思? 外键(FK)是用于建立和加强两个表数据之间的链接的一列或多列.通过将保存表中主键值的一列或多列添加到另一个表中,可创建两个表之间的链接.这个列就成为第二个表的外键. 当创建或更 ...
最新文章
- MyBatis知多少(12)私有数据库
- Android - could not install *smartsocket* listener
- SAP Kyma上创建的Lambda function背后的技术实现
- 第一百三十五期:如何模拟一次阿里双11秒杀场景的实现?程序员必看
- vs2008下如何部署arcengine开发的程序
- 3d旋转相册代码源码_用代码制作3d相册签到墙(附源码)
- 研究生期间如何成为科研大佬?
- PyTorch入门(二)从零开始搭建一个神经网络
- 【CF1355E】Restorer Distance(整数三分)--附整数/浮点三分模板
- 苹果官网html简单代码,苹果官网CSS3应用案例分析
- 强东变法——京东能否逢凶化吉?
- python网址下载文件语言_python爬虫实战之自动下载网页音频文件
- 微软中国招聘职位描述(英文)
- 24寸4驱java山地车_我自己亲身骑过24和26寸山地车,说说我的感受
- tp路由器虚拟服务器架设传奇,单机传奇架设教程2021年完整版
- c语言程序设计对称字符串,清华大学C语言程序设计 L13_字符串精选.pdf
- 一级域名怎么申请二级域名
- 了解vue中的v-model,通俗易懂!
- Matlab 矩阵的LU分解矩阵(公开代码)
- 河南城建学院matlab报告,河南城建学院MATLAB上机实验答案