数据库模型关系

2022-09-14 17:26:08 浏览数 (2)

一、概述

  • 主表 没有声明关系的表为主表
  • 从表 声明关系的表为从表
  • 对应关系
    • 1:1 一对一
    • 1:N 一对多
    • M:N 多对多
  • 一对一以及一对多共同属性on_delete
    • 作用 控制删除
      • models.CASCADE 默认值 当主表的数据删除 则从表数据 默认删除
      • models.PROTECT 保护模式 删除主表数据,如果从表中有关联的数据则无法实现删除 删除从表数据,主表数据不动
      • models.SET_NULL 空值模式 当主表数据被删除 则从表外的字段的值 设置为null 一定将这个字段 设置为null=True
      • models.SET_DEFAULT 默认值模式

二、一对一

说明

使用OneToOneField创建1对1的模型关系 将要创建对应关系的模型添加OneToOneField

使用场景

表的字段太多,需要拆分

关系的位置

哪张表都可以

创建模型 User和IdCard

创建模型 User

代码语言:javascript复制
<span class="hljs-comment">#创建用户表</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span><span class="hljs-params">(models.Model)</span>:</span>
    username = models.CharField(max_length=<span class="hljs-number">20</span>,db_index=<span class="hljs-keyword">True</span>,null=<span class="hljs-keyword">True</span>)
    sex = models.BooleanField(default=<span class="hljs-keyword">True</span>)
    age = models.IntegerField(default=<span class="hljs-number">20</span>)
    info = models.CharField(max_length=<span class="hljs-number">100</span>,default=<span class="hljs-string">'info'</span>)
    icon = models.CharField(max_length=<span class="hljs-number">60</span>,default=<span class="hljs-string">'default.jpg'</span>)
    isDelete = models.BooleanField(default=<span class="hljs-keyword">False</span>)
    createTime = models.DateTimeField(auto_now_add=<span class="hljs-keyword">True</span>)
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        db_table = <span class="hljs-string">'users'</span>

创建模型IdCard 并添加模型一对一关系 OneToOneField

代码语言:javascript复制
<span class="hljs-comment">#1对1的表关系</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IdCard</span><span class="hljs-params">(models.Model)</span>:</span>
    num = models.CharField(max_length=<span class="hljs-number">18</span>)
    name = models.CharField(max_length=<span class="hljs-number">8</span>)
    sex = models.BooleanField(default=<span class="hljs-keyword">True</span>)
    birth = models.DateTimeField(auto_now_add=<span class="hljs-keyword">True</span>)
    address = models.CharField(max_length=<span class="hljs-number">100</span>,default=<span class="hljs-string">'地址'</span>)
    <span class="hljs-comment"># user = models.OneToOneField(User) #1对1的外键 默认删除</span>
    <span class="hljs-comment"># 保护模式 如果删除主表中与从表对应关系的数据 则不能删除</span>
    <span class="hljs-comment"># user = models.OneToOneField(User,on_delete=models.PROTECT)</span>
    <span class="hljs-comment"># 保护模式</span>
    user = models.OneToOneField(User,on_delete=models.SET_NULL,null=<span class="hljs-keyword">True</span>) 
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        db_table = <span class="hljs-string">'idcards'</span>    

一对一数据添加

说明:先添加主表数据 通过主表数据关联添加从表数据

添加主表User数据

代码语言:javascript复制
<span class="hljs-comment">#添加用户信息</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">adduser</span><span class="hljs-params">(req)</span>:</span>
    u = User.addUser(<span class="hljs-string">'lucky'</span>)
    u.save()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'添加用户信息'</span>)

添加从表IdCard数据

代码语言:javascript复制
<span class="hljs-comment">#添加1对1的idcard数据</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">addIdCard</span><span class="hljs-params">(req)</span>:</span>
 		<span class="hljs-keyword">import</span> random
    u = User.objects.first()
    idcard = IdCard(num=random.randrange(<span class="hljs-number">1000000000</span>,<span class="hljs-number">10000000000</span>),name=<span class="hljs-string">'lucky'</span>,user=u)
    idcard.save()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'添加卡的信息'</span>)

一对一数据查询–主获取从

说明:关系是隐性属性

格式:主表对象.从表模型类名小写.从表属性

需求:通过一用户,获取他的身份信息

代码语言:javascript复制
<span class="hljs-comment">#数据查询</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">showOneToOne</span><span class="hljs-params">(req)</span>:</span>
    u = User.objects.first()
    print(u.idcard) <span class="hljs-comment">#idcard关联的数据</span>
    print(u.idcard.num) <span class="hljs-comment">#取出idcard对象的num属性</span>
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'一对一数据的查询'</span>)

一对一数据查询–从获取主

说明:关系是直接声明的,它是一个显性的属性

格式:从表对象.外键属性.主表属性

需求:通过身份证信息查询用户的信息

代码语言:javascript复制
<span class="hljs-comment"># 数据查询</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">showOneToOne</span><span class="hljs-params">(req)</span>:</span>
  idcard = IdCard.objects.first()
  print(idcard.user)  <span class="hljs-comment">#查询卡对应用户的对象</span>
  print(idcard.user.icon) <span class="hljs-comment">#查询卡对应用户的对象的icon属性</span>
 <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'一对一数据的查询'</span>)

一对一数据的删除

说明:删除主表和从表查看关系变化以及更改on_delete属性

删除主表数据

代码语言:javascript复制
<span class="hljs-comment">#数据的删除</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">deleteOneToOne</span><span class="hljs-params">(req)</span>:</span>
    <span class="hljs-comment">#删除主表数据   默认从表数据随着主表数据而删除</span>
    u = User.objects.first()
    u.delete()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'删除了第一个主表的数据'</span>)

删除从表数据

代码语言:javascript复制
<span class="hljs-comment">#数据的删除</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">deleteOneToOne</span><span class="hljs-params">(req)</span>:</span>
    <span class="hljs-comment">#删除从表数据  主表数据 没有改变</span>
    idcard = IdCard.objects.first()
    idcard.delete()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'删除了第一条从表的数据'</span>)

三、一对多

说明

使用ForeignKey创建一对多的模型关系 将要创建对应关系的模型添加ForeignKey

关系的位置

写在多的那一端

创建模型 grade和students

代码语言:javascript复制
<span class="hljs-comment">#班级表</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Grade</span><span class="hljs-params">(models.Model)</span>:</span>
    gname = models.CharField(max_length=<span class="hljs-number">15</span>)
    gnum = models.IntegerField()
    ggirlnum = models.IntegerField()
    gboynum = models.IntegerField()
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        db_table = <span class="hljs-string">'grades'</span>
代码语言:javascript复制
<span class="hljs-comment">#学生表</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Students</span><span class="hljs-params">(models.Model)</span>:</span>
    sname = models.CharField(max_length=<span class="hljs-number">10</span>)
    ssex = models.BooleanField(default=<span class="hljs-keyword">True</span>)
    sage = models.IntegerField(default=<span class="hljs-number">20</span>)
    sgrade = models.ForeignKey(Grade, on_delete=models.CASCADE) <span class="hljs-comment">#1对多的外键 默认删除</span>
    <span class="hljs-comment"># sgrade = models.ForeignKey(Grade,on_delete=models.PROTECT) #保护模式 如果删除主表中与从表对应关系的数据 则不能删除</span>
    <span class="hljs-comment"># sgrade = models.ForeignKey(Grade,on_delete=models.SET_NULL, null=True)  # 保护模式</span>
    <span class="hljs-comment"># sgrade = models.ForeignKey(Grade, on_delete=models.SET_DEFAULT, default=1)  # 设置默认值</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-keyword">return</span> self.sname
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        db_table = <span class="hljs-string">'students'</span>

一对多数据添加

说明:先添加主表数据 通过主表数据关联添加从表数据

添加班级数据

代码语言:javascript复制
<span class="hljs-comment">#添加grade信息</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">addGrade</span><span class="hljs-params">(req)</span>:</span>  				   Grade(gname=<span class="hljs-string">'python1807'</span>,gnum=<span class="hljs-number">63</span>,ggirlnum=<span class="hljs-number">6</span>,gboynum=<span class="hljs-number">57</span>).save()   Grade(gname=<span class="hljs-string">'python1808'</span>,gnum=<span class="hljs-number">50</span>,ggirlnum=<span class="hljs-number">2</span>,gboynum=<span class="hljs-number">48</span>).save()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'添加grade信息'</span>)

给班级添加对应学生数据

代码语言:javascript复制
<span class="hljs-comment">#添加students信息</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">addStudents</span><span class="hljs-params">(req)</span>:</span>
    Students(sname=<span class="hljs-string">'孙悟空'</span>,sgrade=Grade.objects.get(pk=<span class="hljs-number">1</span>)).save()
    Students(sname=<span class="hljs-string">'猪八戒'</span>,sgrade=Grade.objects.get(pk=<span class="hljs-number">1</span>)).save()
    Students(sname=<span class="hljs-string">'沙僧'</span>,sgrade=Grade.objects.get(pk=<span class="hljs-number">2</span>)).save()
    Students(sname=<span class="hljs-string">'唐僧'</span>,sgrade=Grade.objects.get(pk=<span class="hljs-number">2</span>)).save()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'添加students信息'</span>)

一对多数据查询–主获取从

说明:关系是隐性属性

格式:主表对象.从表模型类名小写_set.过滤器

需求:已知一个班级,获取该班级中的所有学生

代码语言:javascript复制
<span class="hljs-comment">#1对多查询</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">oneToManyShow</span><span class="hljs-params">(req)</span>:</span>
    g = Grade.objects.get(pk=<span class="hljs-number">1</span>)
    s = g.students_set.all()
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> s:
        print(i)
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'查询一对多'</span>)

一对多数据查询–从获取主

说明:关系是直接声明的,它是一个显性的属性

格式:从表对象.外键属性.主表属性

需求:已知一个学生,获取该学生所在班级的信息

代码语言:javascript复制
<span class="hljs-comment"># 一对多查询</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">oneToManyShow</span><span class="hljs-params">(req)</span>:</span>
  s = Students.objects.get(pk=<span class="hljs-number">1</span>)
  s = s.grade.name  
  <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'查询一对多'</span>)

一对多数据删除

删除主表数据 (查看从表数据变化)

代码语言:javascript复制
<span class="hljs-comment">#删除主表数据  默认还是 主表数据删除 从表对应数据也被删除</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">deleteGrade</span><span class="hljs-params">(req)</span>:</span>
    g = Grade.objects.first()
    name = g.gname
    g.delete()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'删除主表数据{}'</span>.format(name))

删除从表数据 (查看主表数据变化)

代码语言:javascript复制
<span class="hljs-comment">#删除主表数据  默认还是 主表数据删除 从表对应数据也被删除</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">deleteStudents</span><span class="hljs-params">(req)</span>:</span>
    s = Students.objects.first()
    name = s.gname
    s.delete()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'删除从表数据{}'</span>.format(name))

四、多对多

说明

使用ManyToManyField创建多对多的模型关系 将要创建对应关系的模型添加ManyToManyField

原理

底层是通过两个外键实现,单独有一张表来管理外键,自动生成

关系的位置

哪张表都可以

创建模型 User和Posts

代码语言:javascript复制
<span class="hljs-comment">#创建用户表</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span><span class="hljs-params">(models.Model)</span>:</span>
    username = models.CharField(max_length=<span class="hljs-number">20</span>,db_index=<span class="hljs-keyword">True</span>,null=<span class="hljs-keyword">True</span>)
    sex = models.BooleanField(default=<span class="hljs-keyword">True</span>)
    age = models.IntegerField(default=<span class="hljs-number">20</span>)
    info = models.CharField(max_length=<span class="hljs-number">100</span>,default=<span class="hljs-string">'info'</span>)
    icon = models.CharField(max_length=<span class="hljs-number">60</span>,default=<span class="hljs-string">'default.jpg'</span>)
    isDelete = models.BooleanField(default=<span class="hljs-keyword">False</span>)
    createTime = models.DateTimeField(auto_now_add=<span class="hljs-keyword">True</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-keyword">return</span> self.username
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        db_table = <span class="hljs-string">'user'</span>
代码语言:javascript复制
<span class="hljs-comment">#以下为多对多  posts关联用户</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Posts</span><span class="hljs-params">(models.Model)</span>:</span>
    title = models.CharField(max_length=<span class="hljs-number">20</span>,default=<span class="hljs-string">'标题'</span>)
    article = models.CharField(max_length=<span class="hljs-number">200</span>,default=<span class="hljs-string">'article'</span>)
    createtime = models.DateTimeField(auto_now=<span class="hljs-keyword">True</span>)
    users = models.ManyToManyField(User)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-keyword">return</span> self.title
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        db_table = <span class="hljs-string">'posts'</span>

多对多添加数据

User与Posts模型数据正常添加

代码语言:javascript复制
<span class="hljs-comment">#添加用户信息</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">adduser</span><span class="hljs-params">(req)</span>:</span>
    u = User.addUser(<span class="hljs-string">'lucky'</span>)
    u.save()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'添加用户信息'</span>)
  
<span class="hljs-comment">#添加posts信息</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">addPosts</span><span class="hljs-params">(req)</span>:</span>
    Posts(title=<span class="hljs-string">'以后的你感谢现在拼搏的自己'</span>).save()
    Posts(title=<span class="hljs-string">'阿甘正传'</span>).save()
    Posts(title=<span class="hljs-string">'斗罗大陆'</span>).save()
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'添加Posts信息'</span>)

添加一个多对多的数据 add

代码语言:javascript复制
<span class="hljs-comment">#添加收藏</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">addColl</span><span class="hljs-params">(req)</span>:</span>
    u1 = User.objects.first()
    p1 = Posts.objects.first()
    p1.users.add(u1)
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'添加多对多的数据'</span>)

添加多个多对多的数据 add

代码语言:javascript复制
<span class="hljs-comment">#添加收藏</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">addColl</span><span class="hljs-params">(req)</span>:</span>
    u1 = User.objects.first()
    u2 = User.objects.last()
    p = Posts.objects.get(pk=<span class="hljs-number">2</span>)
    p.users.add(u1,u2) <span class="hljs-comment">#添加多个对象</span>
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'添加多对多的数据'</span>)

多对多数据查询–主获取从

说明:关系是隐性属性

格式:主表对象.从表模型类名小写_set.过滤器

需求:查询用户收藏哪些帖子

代码语言:javascript复制
<span class="hljs-comment">#查询 用户收藏了哪些帖子</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">showPosts</span><span class="hljs-params">(req)</span>:</span>
    u = User.objects.first()
    data = u.posts_set.all()
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> data:
        print(i)
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'查询收藏了哪些帖子'</span>)

多对多数据查询 从获取主

说明:关系是直接声明的,它是一个显性的属性

格式:从表对象.外键属性.过滤器

需求:已知一个博客 查询都被哪些用户收藏

代码语言:javascript复制
<span class="hljs-comment">#查看帖子对应多的关系</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">showUsers</span><span class="hljs-params">(req)</span>:</span>
    p1 = Posts.objects.first()
    data = p1.users.all()
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> data:
        print(i)
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'查询帖子被哪些用户收藏了'</span>)

多对多数据删除

删除一条数据

代码语言:javascript复制
<span class="hljs-comment">#删除</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">deleteData</span><span class="hljs-params">(req)</span>:</span>
    p1 = Posts.objects.first()
    u1 = User.objects.first()
    p1.users.remove(u1)
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'1号用户取消收藏1号帖子'</span>)

删除多条数据

代码语言:javascript复制
<span class="hljs-comment">#删除</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">deleteData</span><span class="hljs-params">(req)</span>:</span>
    p2 = Posts.objects.get(pk=<span class="hljs-number">1</span>)
    u1 = User.objects.first()
    u2 = User.objects.get(pk=<span class="hljs-number">2</span>)
    p2.users.remove(u1,u2)
    <span class="hljs-keyword">return</span> HttpResponse(<span class="hljs-string">'1、2号用户取消收藏1号帖子'</span>)

0 人点赞