Django(part32)--一对一映射

学习笔记,仅供参考



数据表关联关系映射


在关系型数据库中,通常不会把所有数据都放在同一张表中,这样做会额外占用内存空间,这时,我们会使用表关联对各个数据表进行联结。


  • 常用的表关联方式有三种:

    • 一对一映射(如: 一个身份证对应一个人)

    • 一对多映射(如: 一个班级可以有多个学生)

    • 多对多映射(如: 一个学生可以报多个课程,一个课程可以有多个学生学习)


一对一映射


一对一是表示事物之间存在的一对一的对应关系。


语法


#主类
class A(model.Model):
    ...

#从属类
class B(model.Model):
    属性 = models.OneToOneField(A)

  • 例子(作家和作家伴侣类)
#models.py
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)  
    # 增加与作家的一对一属性


创建一对一的数据记录


from bookstore import models
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找author
from 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 makemigrations
Migrations 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 models
author1 = models.Author.objects.create(name='黄永祥', age = 40, email="[email protected]")
partner1 = models.Partner.objects.create(name='黄夫人', age = 39, author=author1)
#关联黄永祥作家
author2 = models.Author.objects.create(name='王军', age = 36, email="[email protected]")  

再查看一下mywebdb数据库中 bookstore_partner表和bookstore_author表:

mysql> select * from bookstore_author;
+----+--------+-----+----------------------+
| id | name   | age | email                |
+----+--------+-----+----------------------+
|  1 | 山羊   |  20 | [email protected] |
|  2 | 小黄   |  11 | [email protected]    |
|  5 | 小黑   |  13 | [email protected]    |
|  6 | 小白   |  19 | [email protected]    |
|  7 | 山羊哥 |  28 | [email protected]    |
|  8 | 黄永祥 |  40 | [email protected]      |
|  9 | 王军   |  36 | [email protected]      |
+----+--------+-----+----------------------+
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, '还没有伴侣')

输出:

黄夫人 的伴侣是 黄永祥
黄永祥 的伴侣是 黄夫人
王军 还没有伴侣

猜你喜欢

转载自blog.csdn.net/m0_37422217/article/details/106893849