Python——Django框架(四)、ORM多表操作之一对多(增删改查)

Pyhton——Django框架(四)

参考博文:https://www.cnblogs.com/yuanchenqi/articles/6083427.html

一、ORM多表操作之一对多

1、一对多增加记录

注意!

首先先来一个需要注意的地方:
有的人建立外键,可能会报错,因为建立的类顺序有问题(ForeignKey括号里面没有加引号才会有这种问题)!
在这里插入图片描述
上图中,Book里面的publish作为外键,如果ForeignKey里面没有加引号,当然可以,但是publish作为外键,如果放到了 Book 的前面,就会报错!所以如果加了引号,就没有顺序问题。

还有一个地方:
在这里插入图片描述
错误原因是在建立外键时要加on_delete.

原因如下:

django 升级到2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常:
TypeError: init() missing 1 required positional argument: ‘on_delete’

on_delete=None, # 删除关联表中的数据时,当前表与其关联的field的行为

on_delete=models.CASCADE, # 删除关联数据,与之关联也删除

on_delete=models.DO_NOTHING, # 删除关联数据,什么也不做

on_delete=models.PROTECT, # 删除关联数据,引发错误ProtectedError

# models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True)
on_delete=models.SET_NULL, # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理)

# models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值')
on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理)

on_delete=models.SET, # 删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

由于多对多(ManyToManyField)没有 on_delete 参数,所以以上只针对外键(ForeignKey)和一对一(OneToOneField)

a、方式一

举个例子,书与出版社,一般来说书只有一个出版社,但是一个出版社可以出多本书,所以,多的一方是书。

那么这里要设立一个外键。注意:外键一定是多的一方!

在这里插入图片描述ForeignKey里面要写你要关联的那张表! 这里publish不用加id(也就是 publish_id),因为数据库会默认给你加上(你要是非要加,就会变成publish_id_id)。

在这里插入图片描述

创建数据的时候,publish作为外键,一定得有值(也就是id需要有),不然就会报错。

接着就是创建数据库,创建表(这些就不说了,前面有),但是有地方要注意:
在这里插入图片描述
接着就是创建数据:
在这里插入图片描述可以看到,这里想创建id为3的外键,失败了。意思是如果想要创建id为3的publish_id,就得在publish里面创建一个id为3的记录。

接着就是写一对多的逻辑(增加记录):
首先是先要引入models里面的字段:
在这里插入图片描述
好,接着写:
在这里插入图片描述
写到这,可以发现就剩 publish_id ,这个该怎么写呢?
在这里插入图片描述
虽然一开始创建的时候没有写 id ,但是这里需要自己手动写上id(注意,addbook后面要加参数,前面忘记了)。

然后可以看到,数据成功加上了:
在这里插入图片描述

b、方式二

可以看到前面创建数据的时候是要 publish_id 的。但还有另外一种方法,不用这个id:
在这里插入图片描述
解释:
在这里插入图片描述
然后把这个对象赋值给了publish_obj,接着后面的操作 publish = publish_obj ,这个操作会自动把 id 给到publish。 相对于上面的操作,这种操作多做了一步。

为了验证是否成功,改下数据看看:
在这里插入图片描述
在这里插入图片描述
可以看到,成功了。

2、一对多查询

我们怎么查看 book 关联的 publish 这张表的信息呢?
先来看下如下操作:
在这里插入图片描述
可以看到拿到的数据类型。是一个对象,既然拿到了对象,就可以通过 点 “ . ” 的方式,来取得我们想要的数据:
在这里插入图片描述
可以看到,数据出来了。

这种通过 点 “ . ”的方式,取得的外键,一定是一个对象!

a、小测试(方式一)

这里做个小测试,看图:
在这里插入图片描述
这里的 Book.objects… 到values 之前为止,做的操作是筛选出集合,而不是一本书(因为可能有多本书)。接着取得这两本书的 名字,价格,看图:
在这里插入图片描述
可以看到能够成功取得数据。

这种方式是先找到出版社名字为 “人民出版社” 的对象集合,再以这个为条件,从Book里面筛选信息。

但是这种方式有点麻烦

a、小测试(方式二)

这里要先来看个新的语法:
xxx_set —— 这种语法是个固定搭配!
在这里插入图片描述
这种方式是先找到出版社名字为 “人民出版社” 的出版社,再找到这个出版社出过的书籍对象。

a、小测试(总结)

总结:
两种方式,一个是正向查找,一个是反向查找。

一个是从书里面找某个特定条件的对象;另一个是先找到这个特定条件的对象,再找这个对象所出过的书。

一个是Book.publish, 另外一个是 publish.book_set

在这里插入图片描述取出来后一样可以做这种操作!

3、一对多查询之双下划线查询

上面的查询,都是通过对象来查询的,也有点麻烦。

但是还有另外一种查询,主要是基于 filter, values, 双下划线 “__”,

来,同样是找出版社为:人民出版社 的书,就可以这样:
在这里插入图片描述
解释:这里的 publish__name 里,publish 是外键的字段,是models文件里,Book设置的外键字段:
在这里插入图片描述
根据这个字段去找,然后双下划线之后的 __name ,就是找这个外键字段里面的 name ,所对应的值,也就是“人民出版社”这个值,找到这个数据。

小测试一:
查找 python 这本书出版社的名字:

方式一:通过publish来查找
在这里插入图片描述上面操作解释为:在publish 里面找,书的名字是python 的出版社名字

方式二:通过Book来查找

在这里插入图片描述
上面操作解释为:找到书的名字是 python 的书,再接着找它出版社的名字。

小测试二:
先来看下数据:
在这里插入图片描述
需求:查找日期为2017年上半年出过的书。

在这里插入图片描述在这里插入图片描述
结果:
在这里插入图片描述
成功取到数据!

4、一对多之修改,删除

修改通过 update() 方法,或者重新赋值。

至于删除,应该跟一对一操作是一样的,但是有外键的存在,如果删除了对应的外键,那么外键以及外键对应的数据也会删除。

猜你喜欢

转载自blog.csdn.net/qq_41824825/article/details/114045500