表关系

1、关系型数据库的表与表之间往往存在一定的关系,由于Django的模型是数据库表与Python类之间的映射,因此Django提供了3种最常用的数据库表之间关系的支持:一对多、一对一、多对多

2、表之间的关系都是通过外键来进行关联的:所以我感觉这里的表关系其实就是对我们前面学习的外键进行的补充(在外键的基础上在进行细分)

 

 

一对多

1、一对多关系:是一张数据库表中的一条记录与另一张数据库表中的多条记录相关的关联模式

2、在关系型数据库中通常使用外键来表示一对多关系:其实我们前面学习的外键就是使用的一对多

3、实现方式:一对多(也叫多对一),都是通过ForeignKey来实现的。ForeignKey与其他模型字段的使用基本相同,唯一不同之处是ForeignKey字段的第一个参数是与当前模型相关联的模型类

4、应用场景:比如文章和作者之间的关系,一篇文章只能有一个作者,但是一个作者可以有多篇文章。文章与作者之间的关系就是典型的一对多(或多对一)的关系

 

插入数据

例1:主表、子表都插入全新数据
⑴编辑模型类
Django:模型_ORM表关系

⑵编辑视图
Django:模型_ORM表关系

注:上面例子中
1、需要先保存子表中的数据:在Django中,会先去判断category或author中数据是否已经存在,如果不存在的话就会报错,如果存在的话才会存进去

2、在Django中:对用于关联的外键进行赋值(存数据)时,只需要使用这种办法就可以了(子表实例名.外键属性名=主表数据值)
    ⑴因为在这个例子中我们三个数据库表的值都是全新存进去的,因此就使用:子表实例名.外键属性名=主表实例名。其实就是将主表中的对应数据赋值给子表中的外键字段(Django会自动将主表数据的ID值赋值给子表的外键字段)
    ⑵还有一种情况就是:子表外键字段的值,不是同时存进去的,而是主表中已经存在的。总的来说还是:将主表中的对应数据赋值给子表中的外键字段

⑶查看数据库
Django:模型_ORM表关系
Django:模型_ORM表关系
Django:模型_ORM表关系

 

例1_1:主表已存在数据,子表存入新数据
⑴编辑模型
    模型与上面例子一样

⑵编辑视图
Django:模型_ORM表关系
注:
1、这个例子中就是将主表中已有的数据的id值赋值给子表的外键值,可以看出其实跟例1的外键字段赋值差不多:子表实例名.子表外键属性名=主表数据值

2、这个例子中查询主表中的数据时是使用的get()。当然这里也可以使用其他的方法来查询出我们需要的数据:fitler()、first()等

⑶查看数据库
Django:模型_ORM表关系
Django:模型_ORM表关系
Django:模型_ORM表关系

 

查询数据

例2:查询子表中的数据(通过子表来查询主表的数据)
⑴编辑视图
Django:模型_ORM表关系

⑵编辑模板
Django:模型_ORM表关系

⑶访问
Django:模型_ORM表关系

注:从上面例子可以看出
只要是直接查询子表中的数据或是通过子表来查询主表中的数据,在视图函数或模板中获取具体列的值的方法都是一样的:
    ⑴要获取的列在子表中,获取方式为:子表实例名.子表模型属性名(列名)
    ⑵要获取的列在主表中,获取方式为:子表实例名.子表模型外键属性名.主表模型属性名(列名)


例2_1:查询主表中的数据(通过主表来查询子表中的数据)
场景:如获取某一个分类下面的所有文章

⑴编辑视图
Django:模型_ORM表关系

⑵编辑模板
Django:模型_ORM表关系

⑶访问
Django:模型_ORM表关系

注:从上面例子可以看出
1、通过主表来获取子表中的数据时使用的方法为:主表实例名.小写子表模型类名_set
    ⑴主表:被引用的数据库表(一对多中的一)
    ⑵子表:引用其他表的表(一对多中的多)

2、在这里例子中我们在获取子表的数据时使用的是"category.article_set.all()":article_set这个属性我们在定义Category模型类时都没有定义这个属性,但是在中编辑器可以自动补全且可以正常使用,这是为什么呢
    ⑴在Django中,如果一个模型(的属性)被其他模型以外键的方式引用了,那么Django就会自动的给这个模型添加一个属性,这个属性就叫做"引用的模型类的名字的小写形式再加上_set"(两个数据库表的关系为一对多)
    ⑵在这个例子中就是:Category模型类中的name属性(列)被Article模型类以外键的形式引用了,因此Django就会给Category模型类自动添加一个"article_set"的属性。通过这个属性,我们就可以通过主表来查询子表中的对应数据了
    ⑶article_set属性返回的是一个类似于"QuerySet对象"的对象,叫做"RelatedManager",这个对象的用法跟objects的用法差不多,因此这个对象后面也可以调用all()、get()、first()、filter()等方法

3、在通过主表查询子表中的数据时,如果不想使用Django内置的主表属性"小写子表模型类名_set"的话,还可以自定义这个主表的属性的名字
    ⑴定义方法为:在子表模型类中的外键属性中定义一个"related_name"的参数,其值就是这里所说的主表属性。与"小写子表模型类名_set"是一样的只是说名字不一样而已
    ⑵如果在字表的外键属性中定义了"related_name"参数的话,在通过主表查询字表的数据时,就只能使用这个"related_name"参数值了,就不能再使用"小写子表模型类名_set"了

例2_2:
⑴编辑模型
Django:模型_ORM表关系

⑵编辑视图
Django:模型_ORM表关系

 

 

 

一对一

1、这种映射关系一般用得比较少,比较常用的场景是根据一张表的主键来对这张表进行扩展

2、应用场景:比如一个用户表(user)和一个用户信息表(user_info)。在实际网站中,可能需要保存用户的许多信息,但是有些信息是不经常用的,如果把所有信息都放到一张表中的话可能影响查询效率,因此就可以把用户的一些不常用的信息存放到另外一张表中。这里的用户表(user)和一个用户信息表(user_info)就是典型的一对一关系了

3、实现方法:Django为一对一提供了一个专门的Field叫做OneToOneField来实现一对一操作
    ⑴OneToOneField:实际上也是表示外键的Field,跟前面的ForeignKey是差不多的,只是说OneToOneField用于一对一,ForeignKey用于一对多。且OneToOneField这个外键有一个唯一约束(unique key)
    ⑵OneToOneField属性的第一个参数也是被引用的模型类的类名

例3:插入数据
⑴编辑模型
Django:模型_ORM表关系

⑵编辑视图
Django:模型_ORM表关系

⑶查看数据库
Django:模型_ORM表关系
Django:模型_ORM表关系


例3_1:继续使用author_id=1的数据来存数据
⑴编辑视图
Django:模型_ORM表关系

⑵访问
Django:模型_ORM表关系

注:从上面两个例子的输出结果可以看出
1、一对多与一对一在插入数据的方式上是没有区别的,但是对于插入的数据值就有区别了
    ⑴一对多:主表中的一条数据可以被子表中的多条数据引用
    ⑵一对一:主表中的一条数据只能被子表中的一条数据引用。如果子表中多条数据引用了主表中的同一条数据的话,就会报错


例3_2:通过子表查询主表
⑴编辑视图
Django:模型_ORM表关系


例3_3:通过主表查询子表
⑴编辑视图
Django:模型_ORM表关系

注:从上面例子可以看出
1、author.authorinfo:当一个模型类被另一个模型类作为外键引用且引用关系为一对一时,那么Django就会自动给这个模型(主表)添加一个"小写子表模型类名"的属性。我们可以使用这个属性来根据主表查询子表中的数据

2、可以看出一对一与一对多在查询数据的方式上还有有点不一致的:
    ⑴根据子表来查询主表:一对一与一对多查询方式一致:子表实例名.子表外键属性名.主表属性名
    ⑵根据主表来查询子表:一对一的主表属性为"小写子表模型类名",一对多的主表属性为"小写子表模型类名_set"

3、当然在一对一表关系中,也可以在子表属性中定义"related_name"参数,使用方法与条件与一对多表关系一致

 

 

多对多

1、应用场景:比如文章和标签的关系。一篇文章可以有多个标签,一个标签也可以被多篇文章所引用。因此标签与文章的关系就是典型的多对多的关系

2、实现代码:Django中为这种多对多的实现提供了专门的Field,叫做ManyToManyField

3、对于多对多关系,Django会在数据库中额外创建一张表,这张表称为中间表,该表的命名规则是:应用程序_模型1名_模型2名s

例4:多对多模型关系理解
Django:模型_ORM表关系

注:
1、上面图中,中间的那张表就是Django自动生成的中间表(这张表也可以自己定义)。这张表就是用来存储来两张关系表的多对多关系的数据

2、比如这个例子中,如果需要找"文章1"下面的标签,那么就可以去中间表中找"文章1"下对应的标签

3、自己感觉:两个模型关系为多对多时,它们两个模型(表)其实是没有直接关系的,而是将两个表中有关系的数据存储到中间表中

4、只要两个模型为多对多关系时,那么肯定就会有一个中间表,一般下我们操作数据也是在中间表中操作的


例4_1:
⑴编辑模型
Django:模型_ORM表关系

注:
1、这个例子中分别定义了两个模型类"Article"和"Tag":其中"Tag"模型类中的"article"属性通过外键(多对多)关联到"Article"

2、当然我们也可以把这个多对多的外键定义在"Article"模型类中:tag = models.ManyToManyField("Tag")

3、自己感觉:在多对多关系中没有明确的哪个表引用哪个表(哪个表是主表哪个表是子表),因为它相互引用的关系。因此在定义多对多外键时,定义在哪个表中都是一样的。将外键定义在哪个表中哪个表就是子表
    ⑴可以在两个有多对多关系的模型中的任意一个模型中定义多对多字段,但是不能同时在两个模型中都定义多对多字段
    ⑵且在多对多关系外键属性中也不必须要定义"on_delete"参数

⑵查看生成的数据库表
Django:模型_ORM表关系
Django:模型_ORM表关系
Django:模型_ORM表关系

注:
从实际生成表表中可以看出:两个表的关系为多对多时,实际生成的表与我们定义的模型类是没有什么区别的,只是说会自动生成一个中间表(polls_tag_article)。这个中间表就是用来存储两个表关系数据的(用两个表中的id值进行关联)


⑶编辑视图
Django:模型_ORM表关系

注:
1、在多对多关系中,因为两个关联的数据库表没有直接的关系(无直接的外键关联),因此就不能跟一对多、一对一关系那样使用"子表实例名.子表外键属性名=主表数据值"

2、在这个例子中因为是Tag模型类引用了Article模型类,因此Article模型类就相当于前面的"主表",因此Django就会自动给Article模型类添加一个"小写子表模型类名_set"的属性,我们就可以使用这个属性下面的add()方法来将两个表中的数据进行关联并将数据存到中间表中:主表实例名.小写子表模型类名_set.add(子表数据值)

3、其实在一对一、一对多关系表中也可以使用这种方式"小写子表模型类名_set.add()"来存数据,只是我没有怎么关注

⑷查看数据库
Django:模型_ORM表关系
Django:模型_ORM表关系
Django:模型_ORM表关系


例4_2:新增文件并关联已有的标签
⑴编辑视图
Django:模型_ORM表关系

⑵查看数据库
Django:模型_ORM表关系
Django:模型_ORM表关系
Django:模型_ORM表关系


⑶给已有文章添加新标签
Django:模型_ORM表关系

注:
在多对多表关系中,也可以在子表属性中定义"related_name"参数,使用方法与条件与一对多、一对一表关系一致


例5:主表查询子表
⑴编辑视图
Django:模型_ORM表关系

 

例5_1:子表查询主表
⑴编辑视图
Django:模型_ORM表关系

注:
1、通过子表中的数据来查询主表中的数据时,因为没有子表中没有直接关联主表的外键列,因此就不能使用前面的"子表实例名.子表外键属性名.主表属性名"来进行查询了

2、在多对多关系中,通过子表来查询主表中的数据,可以使用:子表实例名.小写主表模型名.过滤条件来进行查询

 

 


拓展


Pycharm中连接数据库

1、进入连接入口
Django:模型_ORM表关系

2、选择需要连的数据库
Django:模型_ORM表关系

3、下载Java驱动文件
    一般情况下,Pycharm中都会缺少这个Java驱动文件,因此需要我们自己单独下载
Django:模型_ORM表关系
Django:模型_ORM表关系

4、下载驱动文件成功后,填写数据库信息
Django:模型_ORM表关系

5、查看所连数据库中的表
Django:模型_ORM表关系


 

 

 

分类:

技术点:

相关文章: