Django数据映射 一对一 一对多 多对多

数据表关联关系映射

  • 常用的表关联方式有三种:
    1. 一对一映射
      • 如: 一个身份证对应一个人
    2. 一对多映射
      • 如: 一个班级可以有多个学生
    3. 多对多映射
      • 如: 一个学生可以报多个课程,一个课程可以有多个学生学习

一对一映射

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

语法

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

外键类字段选项

  • 特殊字段参数【必须项】:

    • on_delete
      1. models.CASCADE 级联删除。 Django模拟SQL约束ON DELETE CASCADE的行为,并删除包含ForeignKey的对象。
      2. models.PROTECT 抛出ProtectedError 以阻止被引用对象的删除;[等同于mysql默认的RESTRICT]
      3. models.SET_NULL 设置ForeignKey null;需要指定null=True
      4. models.SET_DEFAULT 将ForeignKey设置为其默认值;必须设置ForeignKey的默认值。
      5. … 其它参请参考文档 https://docs.djangoproject.com/en/2.2/ref/models/fields/#foreignkey
  • 其余常用的字段选项【非必须项】;如:

    1. null
    2. unique 等

用法示例

  1. 创建作家和作家妻子类

    # file : xxxxxxxx/models.py
    from django.db import models
    
    class Author(models.Model):
        '''作家模型类'''
        name = models.CharField('作家', max_length=50)
    
    class Wife(models.Model):
        '''作家妻子模型类'''
        name = models.CharField("妻子", max_length=50)
        author = models.OneToOneField(Author, on_delete=models.CASCADE)  # 增加一对一属性 
    
  2. 创建一对一的数据记录

    from .models import *
    author1 = Author.objects.create(name='王老师')
    wife1 = Wife.objects.create(name='王夫人', author=author1)  # 关联王老师
    author2 = Author.objects.create(name='小泽老师')  # 一对一可以没有数据对应的数据 
    
  3. 数据查询

    1. 正向查询

      • 直接通过关联属性查询即可
      # 通过 wife 找 author
      from .models import Wife
      wife = Wife.objects.get(name='王夫人')
      print(wife.name, '的老公是', wife.author.name)
      
    2. 反向查询

      • 通过反向关联属性查询
      • 反向关联属性为实例对象.引用类名(小写),如作家的反向引用为作家对象.wife
      • 当反向引用不存在时,则会触发异常
      # 通过 author.wife 关联属性 找 wife,如果没有对应的wife则触发异常
      author1 = Author.objects.get(name='王老师')
      print(author1.name, '的妻子是', author1.wife.name)
      author2 = Author.objects.get(name='小泽老师')
      try:
          print(author2.name, '的妻子是', author2.wife.name)
      except:
          print(author2.name, '还没有妻子')
      

一对多映射

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

    • 当一个A类对象可以关联多个B类对象时
    class A(model.Model):
        ...
    
    class B(model.Model):
        属性 = models.ForeignKey("一"的模型类, on_delete=xx)
    
  2. 用法示例

    • 有二个出版社对应五本书的情况.
      1. 清华大学出版社 有书

        1. C++
        2. Java
        3. Python
      2. 北京大学出版社 有书

        1. 西游记
        2. 水浒
  3. 创建模型类

    # file: otm/models.py
    from django.db import models
    
    class Publisher(models.Model):
    	'''出版社【一】'''
        name = models.CharField('名称', max_length=50, unique=True)
    
    class Book(models.Model):
        '''书【多】'''
        title = models.CharField('书名', max_length=50)
        publisher = ForeignKey(Publisher, on_delete=models.CASCADE)
        
    
  4. 创建数据

    #先创建 '一' ,再创建 '多'
    from .models import *
    pub1 = Publisher.objects.create(name='清华大学出版社')
    Book.objects.create(title='C++', publisher=pub1)
    Book.objects.create(title='Java', publisher_id=1)
    
    #高级创建 - 利用 反向属性
    pub2 = Publisher.objects.create(name='北京大学出版社')
    pub2.book_set.create(title='西游记')
    
  5. 数据查询

    通过 Book 查询 Publisher【正向】

    通过 publisher 属性查询即可
    book.publisher
     
    abook = Book.objects.get(id=1)
    print(abook.title, '的出版社是:', abook.publisher.name)
    

    通过 Publisher 查询 对应的所有的 Book 【反向】

    Django会在Publisher中增加一个属性来表示对对应的Book们的查询引用
    属性:book_set  等价于 objects
    
    # 通过出版社查询对应的书
    pub1 = Publisher.objects.get(name='清华大学出版社')
    books = pub1.book_set.all()  # 通过book_set 获取pub1对应的多个Book数据对象
    #books = Book.objects.filter(publisher=pub1)  # 也可以采用此方式获取
    print("清华大学出版社的书有:")
    for book in books:
       print(book.title)
    

多对多映射

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

    • 在关联的两个类中的任意一个类中,增加:
    属性 = models.ManyToManyField(MyModel)
    
  2. 用法示例

    • 一个作者可以出版多本图书
    • 一本图书可以被多名作者同时编写
    class Author(models.Model):
        ...
    
    class Book(models.Model):
        ...
        authors = models.ManyToManyField(Author)
    
  3. 创建模型类

    class Author(models.Model):
        '''作家模型类'''
        name = models.CharField('作家', max_length=50)
        def __str__(self):
            return self.name
        
    class Book(models.Model):
        '''书模型类'''
        title = models.CharField('书名', max_length=50)
        authors = models.ManyToManyField(Author)
        def __str__(self):
       		return self.title 
    
  4. 创建数据

    方案1 先创建 author 再关联 book
        author1 = Author.objects.create(name='吕老师')
        author2 = Author.objects.create(name='王老师')
        # 吕老师和王老师同时写了一本Python
        book11 = author1.book_set.create(title="Python")
        author2.book_set.add(book11) 
        
    方案2 先创建 book 再关联 author
        book = Book.objects.create(title='python1')
        #郭小闹和吕老师都参与了 python1 的 创作
        author3 = book.authors.create(name='guoxiaonao')
        book.authors.add(author1)
    
  5. 数据查询

    1. 通过 Book 查询对应的所有的 Author【正向】
    book.authors.all() -> 获取 book 对应的所有的author的信息
    book.authors.filter(age__gt=80) -> 获取book对应的作者中年龄大于80岁的作者的信息
    
    1. 通过 Author 查询对应的所有的Book【反向】
    • Django会生成一个反向属性 book_set 用于表示对对应的book的查询对象相关操作
    author.book_set.all()
    author.book_set.filter()
    

你可能感兴趣的:(Django,django,python,后端)