学习笔记,仅供参考
文章目录
- 数据表关联关系映射
- 一对一映射
- 语法
- 创建一对一的数据记录
- 查询
- 作用
- 举个例子
数据表关联关系映射
在关系型数据库中,通常不会把所有数据都放在同一张表中,这样做会额外占用内存空间,这时,我们会使用表关联对各个数据表进行联结。
- 常用的表关联方式有三种:
- 一对一映射(如: 一个身份证对应一个人)
- 一对多映射(如: 一个班级可以有多个学生)
- 多对多映射(如: 一个学生可以报多个课程,一个课程可以有多个学生学习)
一对一映射
一对一是表示事物之间存在的一对一的对应关系。
语法
class A(model.Model):
...
#从属类
class B(model.Model):
属性 = models.OneToOneField(A)
- 例子(作家和作家伴侣类)
from django.db import models
class Author(models.Model):
'''作家模型类'''
name = models.CharField('作家', max_length=50)
class Partner(models.Model):
'''作家伴侣模型类'''
name = models.CharField("伴侣", max_length=50)
author = models.OneToOneField(Author)
# 增加与作家的一对一属性
创建一对一的数据记录
author1 = models.Author.objects.create(name='黄永祥')
partner1 = models.Partner.objects.create(name='黄夫人', author=author1)
#关联黄永祥作家
author2 = models.Author.objects.create(name='王军')
# 一对一关系中,主类对象可以没有对应的从属类对象
查询
在Partner对象中,通过author属性找到对应的author对象;
在Author对象中,通过 partner属性找到对应的partner对象.
- 正向查询
直接通过关联属性查询即可:
# 通过partner找authorfrom bookstore import models
partner = models.Partner.objects.get(name='黄夫人')
print(partner.name, '的伴侣是', partner.author.name)
- 反向查询
反向查询为通过反向引用属性查询,反向引用属性为实例对象.引用类名(引用类名要小写),如作家的反向引用为作家对象.partner,需要注意的是,当反向引用不存在时,则会触发异常
#author可以通过author.partner查找partner,如果没有对应的partner则触发异常author1 = models.Author.objects.get(name='黄永祥')
print(author1.name, '的伴侣是', author1.partner.name)
author2 = models.Author.objects.get(name='王军')
try:
print(author2.name, '的伴侣是', author2.partner.name)
except:
print(author2.name, '还没有伴侣')
作用
一对一映射主要是解决数据的存储问题,把经常加载的一个数据放在主表中,不常用数据放在另一个副表中,这样,在访问主表数据时就不需要加载副表中的数据,以提高访问速度和节省内存空间,如经常把书的内容和书名建成两张表,因为在网站上经常访问书名等信息,但不需要得到书的内容。
举个例子
首先,我们在models.py中创建一个Partner模型类,并作为Author类的从属类,形成一对一关系:
class Partner(models.Model):'''作家伴侣模型类'''
name = models.CharField("姓名", max_length=50)
age = models.IntegerField("年龄", null = False,
default = 1)
author = models.OneToOneField(Author, on_delete = models.CASCADE)
记得做一下迁移:
F:\MyStudio\PythonStudio\goatbishop.project01\Django\mywebsite_db>python manage.py makemigrationsMigrations for 'bookstore':
bookstore\migrations\0006_auto_20200621_2334.py
- Alter field age on author
- Create model Partner
F:\MyStudio\PythonStudio\goatbishop.project01\Django\mywebsite_db>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, bookstore, contenttypes, sessions
Running migrations:
Applying bookstore.0006_auto_20200621_2334... OK
需要注意的是,如果我们在OneToOneField中没有加参数on_delete=models.CASCADE,则在使用python manage.py makeigrations 进行迁移时就会报错。如果我们加入这个参数,则在删除主表的数据时,从表中的数据也会随之删除。
现在,打开Django shell创建记录:
from bookstore import modelsauthor1 = models.Author.objects.create(name='黄永祥', age = 40, email="yxhuang@163.com")
partner1 = models.Partner.objects.create(name='黄夫人', age = 39, author=author1)
#关联黄永祥作家
author2 = models.Author.objects.create(name='王军', age = 36, email="wangjun@163.com")
再查看一下mywebdb数据库中 bookstore_partner表和bookstore_author表:
mysql> select * from bookstore_author;+----+--------+-----+----------------------+
| id | name | age | email |
+----+--------+-----+----------------------+
| 1 | 山羊 | 20 | goatbishop@gamil.com |
| 2 | 小黄 | 11 | 1033794241@qq.com |
| 5 | 小黑 | 13 | xiaohei@gmail.com |
| 6 | 小白 | 19 | xiaobai@gmail.com |
| 7 | 山羊哥 | 28 | biggoat@gmail.com |
| 8 | 黄永祥 | 40 | yxhuang@163.com |
| 9 | 王军 | 36 | wangjun@163.com |
+----+--------+-----+----------------------+
7 rows in set (0.00 sec)
mysql> select * from bookstore_partner;
+----+--------+-----+-----------+
| id | name | age | author_id |
+----+--------+-----+-----------+
| 1 | 黄夫人 | 39 | 8 |
+----+--------+-----+-----------+
1 row in set (0.00 sec)
我们看到bookstore_partner表中黄夫人的author_id字段值为8,它对应着bookstore_author表中的id值8
我们再做一些查询工作:
#正向partner = models.Partner.objects.get(name='黄夫人')
print(partner.name, '的伴侣是', partner.author.name)
#反向
author1 = models.Author.objects.get(name='黄永祥')
print(author1.name, '的伴侣是', author1.partner.name)
author2 = models.Author.objects.get(name='王军')
try:
print(author2.name, '的伴侣是', author2.partner.name)
except:
print(author2.name, '还没有伴侣')
输出:
黄夫人 的伴侣是 黄永祥黄永祥 的伴侣是 黄夫人
王军 还没有伴侣