数据库实体间有3种对应关系:一对一,一对多,多对多。
- 一对一关系: 一个学生对应一个学生档案编号
- 一对多关系: 一个学生只属于一个班级,但一个班级有多名学生
在
学生表
中添加班级号
字段作为外键,与班级表
的主键关联
- 多对多关系: 一个学生可以选择多门课,一门课也有多名学生选择。
在多对多关系中,通过添加字段无法解决问题,需要创建额外的
关系表
来连接相关数据表
删除数据时,要先删除关系表
中的记录,再删除主表中的记录
模型类中处理3种关系
- 一对一:使用
OneToOneField()
函数,将字段定义在任意模型类中。 - 一对多:使用
ForeignKey()
函数,将字段定义在多的模型类中 - 多对多:使用
ManyToManyField()
函数,将字段定义在任意模型类中 - 可以维护递归的关联关系,使用
self
指定
一对多关系: 一对一关系可以看作一对多的特例
修改models.py
文件中的PersonInfo
类,添加hbook
属性
ORM会在app_personinfo
表中增加hbook_id
字段作为外键,并关联到app_bookinfo
表的id
主键
说明:如果生成迁移文件报错,将migrations目录中除init之外的文件删除
class PersonInfo(models.Model):
...
hbook = models.ForeignKey('BookInfo', on_delete=models.CASCADE)
增加测试数据
INSERT INTO app_personinfo(pname, pgender, pcomment, isDelete, hbook_id) VALUES
('曹操',1,'字孟德',0,1),
('刘备',1,'字玄德',0,1),
('诸葛亮',1,'字孔明',0,1),
('孙权',1,'字仲谋',0,1),
('贾宝玉',1,'荣国府公子',0,2),
('林黛玉',0,'金陵十二钗之冠',0,2),
('薛宝钗',0,'薛姨妈之女',0,2),
('王熙凤',0,'贾琏之妻',0,2),
('贾母',0,'宝玉祖母',0,2),
('宋江',1,'呼保义',0,3),
('卢俊义',1,'玉麒麟',0,3),
('吴用',1,'智多星',0,3),
('公孙胜',1,'入云龙',0,3),
('孙悟空',1,'唐僧的大徒弟',0,4),
('唐僧',1,'玄奘',0,4),
('猪八戒',1,'悟能',0,4),
('沙僧',1,'沙悟净',0,4);
多对多关系:
在models.py
文件中增加新闻类型类
和新闻类
一个新闻类型下可以用多条新闻,一条新闻可以属于多种新闻类型
新闻类型
class TypeInfo(models.Model):
tname = models.CharField(max_length=20) # 新闻类别
新闻
class NewsInfo(models.Model):
ntitle = models.CharField(max_length=60) # 新闻标题
ncontent = models.TextField() # 新闻内容
npub_date = models.DateTimeField(auto_now_add=True) # 新闻发布时间
# 通过ManyToManyField建立TypeInfo类和NewsInfo类之间多对多的关系
typeinfo= models.ManyToManyField('TypeInfo')
执行数据迁移后,自动创建3张表:
- app_typeinfo:新闻类型表
- app_newsinfo:新闻表
- app_newsinfo_typeinfo:关系表
说明:如果要指定关系表的名字,可以使用
througt
参数
添加测试数据
新闻类型
INSERT INTO app_typeinfo(tname) VALUES
('科技'),
('军事'),
('国际')
新闻
INSERT INTO app_newsinfo(ntitle, ncontent, npub_date) VALUES
('互联网科技','马云已退出阿里旗下5家公司:官方称没这个打算','2018-7-24'),
('数码产品','苹果官方科普来了:全面认识Apple ID','2018-6-23'),
('宇宙探索','平行时空、多元宇宙真的存在?令人细思极恐','2018-5-24'),
('国际军情','美国国会议员:前总统吉米·卡特请缨亲赴朝鲜','2017-11-24'),
('中国军情','中国海军万吨巨舰的起点 原型就是这艘民船','2016-5-24'),
('欧洲','欧盟高官警告:特朗普不要搞垮了世贸体系','2017-2-24'),
('美国','伊拉克北部发生汽车炸弹袭击致1死7伤','2016-5-24')
关系表
INSERT INTO app_newsinfo_ntype(newsinfo_id, typeinfo_id) VALUES
(1,1),
(3,1),
(5,1),
(4,2),
(6,2),
(2,3),
(4,3),
(6,3),
(7,3)
实例演示: 使用SQL语句,查询所有新闻标题、内容及其类型
SELECT n.ntitle, n.ncontent, t.tname
FROM app_newsinfo n, app_typeinfo t, app_newsinfo_ntype nt
WHERE n.id = nt.newsinfo_id AND t.id = nt.typeinfo_id