本文介绍: 一对一是表示现实事物间存在的一对一的对应关系。如:一个家庭只有一个户主,一个男人有一个妻子,一个人有一个唯一的身份证号等。一对多是表现现实事物间存在的一对多的对应关系。如:一个学校有多个班级,一个班级有多个学生,一本图书只能属于一个出版社,一个出版社允许出版多本图书。一对多需要明确出具体角色,在多表上设置外键。多对多表达对象之间多对多复杂关系,如:每个人都有不同的学校(小学,初中,高中,…),每个学校都有不同的学生…Mysql中创建多对多需要依赖第三张表来实现。

关系映射

在关系型数据库中,通常不会把所有数据都放在同一张表中,不易于扩展,常见的关系映射有:

  1. 一对一映射,如一个身份证对应一个人。

  2. 一对多映射,如一个班级可以有多个学生。

  3. 多对多映射,如一个学生可以报多个课程,一个课程可以有多个学生学习。

1 一对一映射

1.1 一对一映射定义

  • 一对一是表示现实事物间存在的一对一的对应关系。如:一个家庭只有一个户主,一个男人有一个妻子,一个人有一个唯一的身份证号等。

1.2 一对一映射创建模型

  • 语法:OneToOneField(类名,on_delete=xxx),on_delete:级联删除。

    class A(model.Model):
        ...
    class B(model.Model):
        属性 = models.OneToOneField(A, on_delete=xxx)

  • 特殊字段选项【必须】,on_delete,级联删除。

Django中的一对一映射

  1. models.CASCADE 级联删除,Django模拟SQL约束ON DELETE CASCADE的行为,并删除包含ForegnKey的对象。

  2. models.PROTECT 抛出ProtectedError 以组织被引用对象的删除,等同于 mysql 默认的RESTRICT。

  3. SET_NULL 设置 ForeignKey null,需要指定 null=True;

  4. SET_DEFAULT 将 ForeignKey 设置为其默认值,必须设置ForeignKey默认值。

代码示例:

from django.db import models
​
# 关系说明:一个人只有一个身份证号码,一个身份证号码对应一个人
# Create your models here.
class Person(models.Model):
    """
    个人类
    """
    name = models.CharField("姓名", max_length=11, default='', null=False)
    age = models.IntegerField("年龄", default=1)
    home = models.CharField("住址", max_length=256, default='')
​
    def __str__(self):
        return "%s_%s_%s" % (self.name, self.age, self.email)
​
class IdCard(models.Model):
    """
    身份证件
    """
    idCardNUmber = models.CharField("身份证号码", max_length=32, null=False)
    person = models.OneToOneField(Person, on_delete=models.CASCADE) # 一对一属性

1.3 一对一映射创建数据

# 无外键的模型类[Person]:
person = Person.objects.create(name='南歌', age=20, home='陕西省延安市')
# 有外键的模型类[IdCard]
idcard = IdCard.objects.create(idCardNUmber='xxxx', person=person)
# 也即关联个人的主键值
idcard = IdCard.objects.create(idCardNUmber='xxxx', person_id=person_id)

直接关联外键对应的对象。

数据库查看。

关联外键对应对象的主键值。

数据库查看。

1.4 一对一映射查询数据

  1. 正向查询:直接通过关联的外键属性查询,则称为正向查询。

    # 通过IdCard查找Person
    from oto.models import *
    idCard = IdCard.objects.get(idCardNUmber='xxxx')
    ​
    print("身份证号:{idCardNUmber}的人姓名为:{name}".format(idCardNUmber=idCard.idCardNUmber, name=idCard.person.name))

  2. 反向查询:没有外键属性的一方,可以调用反向属性查询到关联的另一方。

    注:

    • 反向关联属性为 实例对象.引用类名(小写),如个人的反向引用为 个人对象.idcard

    • 当反向引用不存在时,则会触发异常。

    # 通过IdCard查找Person
    from oto.models import *
    ​
    person = Person.objects.get(name='南歌')
    person.idcard.idCardNUmber

    反向属性不存在时,触发异常。

2 一对多映射

2.1 一对多映射定义

  • 一对多是表现现实事物间存在的一对多的对应关系。如:一个学校有多个班级,一个班级有多个学生,一本图书只能属于一个出版社,一个出版社允许出版多本图书。

  • 一对多需要明确出具体角色,在多表上设置外键。

2.2 一对多映射创建模型

  • 语法

    # 当一个A类对象可以关联多个B类对象时
    class A(models.Model):
        ...
        
    class B(models.Model):
        属性  = models.Foreignkey("一"的模型类, on_delete=xx)
    # Fortignkey 必须指定 on_delete模式

代码示例:

from django.db import models
​
# Create your models here.
# 关系说明:一个出版社可以有多本图书,一个图书只能对应一个出版社
class Press(models.Model):
    """
    出版社
    """
    name = models.CharField("名称", max_length=128, unique=True)
​
​
class Book(models.Model):
    """
    图书
    """
    name = models.CharField("书名", max_length=128)
    press = models.ForeignKey(Press, on_delete=models.CASCADE)

2.3 一对多映射创建数据

# 先创建一,再创建多
from otm.models import *
press = Press.objects.create(name="东北大学出版社")
​
Book.objects.create(name="C++教程", press=press)
Book.objects.create(name="Python教程", press_id=press_id)

2.4 一对多映射查询数据

  1. 正向查询:直接通过关联的外键属性查询,则称为正向查询。

    # 通过Book查找Press
    from otm.models import *
    book = Book.objects.get(name='Python教程')
    ​
    print("{book}的出版社是{name}".format(book=book.name, name=book.press.name))

  2. 反向查询:没有外键属性的一方,可以调用反向属性查询到关联的另一方。

    # 通过 Press 查找 Book
    from otm.models import *
    press = Press.objects.filter(name='东北大学出版社')
    books = press.book_set.all()

3 多对多映射

3.1 多对多定义

  • 多对多表达对象之间多对多复杂关系,如:每个人都有不同的学校(小学,初中,高中,…),每个学校都有不同的学生…

  • Mysql中创建多对多需要依赖第三张表来实现。

  • Django中无需手动创建第三张表,Django自动完成。

3.2 多对多映射创建模型

  • 语法:在关联的两个类中的任意一个类中增加:

    属性 = models.ManyToManyField(MyModel)

  • 代码示例:

    # 关系说明:一个作者可以出版多本图书,一本图书可以被多名坐着同时编写
    ​
    from django.db import models
    ​
    # Create your models here.
    class Author(models.Model):
        name = models.CharField("作者", max_length=128)
    ​
    ​
    class Book(models.Model):
        name = models.CharField("书名", max_length=128)
        authors = models.ManyToManyField(Author)

3.3 多对多映射创建数据

# 方案一:先创建author再关联book
author1 = Author.objects.create(name="南歌")
author2 = Author.objects.create(name="EuanSu")
## 南歌和EuanSu同时写了一本《Django教程》
book = author1.book_set.create(name="Django教程")
author2.book_set.add(book)
​
# 方案二:先创建book再关联author
book = Book.objects.create(name="Python教程")
## 南歌和EuanSu都参与了《Python教程》的编写
author = book.authors.create(name="南歌")
book.authors.add(author)

3.4 多对多映射查询数据

  1. 正向查询:直接通过关联的外键属性查询,则称为正向查询。

    # 通过Book查询对应所有的 Author,此时多对多属性等价于objects
    ## 获取 book 对应的所有author信息
    book.authors.all() 
    ## 获取book对应作者中名字为南歌的author
    book.authors.filter(name="南歌")

  2. 反向查询:没有外键属性的一方,可以调用反向属性查询到关联的另一方。

    # 通过Author查询对应所有的book,利用反向属性book_set
    author.book_set.all()
    author.book_set.filter(name="Django教程")

原文地址:https://blog.csdn.net/suu_an/article/details/136014441

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_66159.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注