关于ORM增删改查的总结——跨表

0 环境准备

python 复制代码
from django.db import models


class Clazz(models.Model):
    """
    班级模型类
    """

    # 班级名称
    class_name = models.CharField(max_length=20, unique=True)

    class Meta:
        db_table = 'clazz'


class Courses(models.Model):
    """
    课程模型类
    """

    # 课程名称
    course_name = models.CharField(max_length=20, unique=True)

    class Meta:
        db_table = 'courses'

class StuInfo(models.Model):
    """
    学生详细信息模型类
    """

    # 电话
    tel = models.CharField(max_length=11, unique=True)
    # 邮箱
    email = models.EmailField()
    # 住址
    addr = models.CharField(max_length=100)

    class Meta:
        db_table = 'stu_info'


class Students(models.Model):
    """
    学生模型类
    """
    sex_choice = (
        ("女", 0),
        ("男", 1),
        ("保密", 2)
    )

    # 学生名称
    stu_name = models.CharField(max_length=20)
    # 学生性别
    stu_sex = models.SmallIntegerField(choices=sex_choice, default=2)
    # 学生年龄
    stu_age = models.IntegerField(default=18)
    # 出生日期
    stu_birth = models.DateField()

    # 学生表 与 课程表 ==> 【多对多】
    stu_courses = models.ManyToManyField("Courses", db_table='stu_courses', related_name="stu")

    # 学生表 与 班级表 ==> 【一对多】
    stu_class = models.ForeignKey("Clazz", on_delete=models.CASCADE, related_name="students_list")

    # 学生表 与 学生详细信息表 ==> 【一对一】
    student_to_stuinfo = models.OneToOneField(to="StuInfo", on_delete=models.CASCADE,related_name="stu_list")

    class Meta:
        db_table = 'students'

    def __str__(self):
        return self.stu_name

由上述模型类可知

复制代码
1 表关系及关联字段
	
	学生表 与 班级表 ==> 【一对多】
		关联字段为 stu_class,
		在数据表中该字段名为 stu_class_id
		
	学生表 与 学生详细信息表 ==> 【一对一】
		字段 student_to_stuinfo 即为这两个表的关联字段,
		生成数据表后该字段为 student_to_stuinfo_id,即 字段名_id 的形式
	
	学生表 与 课程表 ==> 【多对多】
		会生成第三张表,表名为 stu_courses,是根据参数 db_table 定义的,
		表中的字段分别是:id,学生表名_id, 课程表名_id

2 外键

2.1 models.ForeignKey() :
	设置外键,
	作用于 一对多 关系的表,通常设置在 "多"表

2.2 models.OneToOneField() :
	本质也是设置外键,且该 外键 设置了 唯一约束
	作用于 一对一 关系的表,
	设置在哪张表都可以,一般设置在字段较多的表

2.3 models.ManyToManyField()
	本质也是设置外键,即第三张表会设置两个外键,关联两张表对应的字段,
	作用于 多对多 关系的表,
	设置在哪张表都可以,一般设置在字段较多的表

3 参数

3.1 db_constraint
	由于在数据表中设置了foreign_key会影响性能,
	所以通常开发时不会显式设置,只做逻辑上的表示即可,
	即 models.ForeignKey() 、models.OneToOneField() 、models.ManyToManyField() 
		都可加上参数 db_constraint = False

3.2 on_delete
	一般值为models.CASCADE,开启级联删除

3.3 related_name
	值为自定义的字符串,
	作用于 跨表 的 反向查询,具体下文4.1.2有提及

引子:关联字段可调用的内置方法 ------------
	
	增:add(模型类对象1, 模型类对象2, ...) 
		详见下文1.3
	
	单个删:remove(id值) 
		详见下文2.2.3 【1】

	批量删:clear() 
		详见下文 2.2.3 【2】
 
 	改:set([n,m]) 
		详见下文 3.2.1 【1】

	查: all() 
		详见下文 4.1.2

1 添加

模型类.objects.create(字段名=字段值, 字段名=字段值, ...),返回模型类对象

1.1 一对一关系 【学生表 与 学生详细信息表】

1.1.1 关联字段所在的表 【学生表】的添加操作

学生表模型类.objects.create(字段名=字段值, 字段名=字段值, ...)
注:关联字段 student_to_stuinfo 受【学生详细信息表】的 id 字段限制,添加时需保证该字段值在【学生详细信息表】中存在

复制代码
一对一的关联字段:student_to_stuinfo
	可通过该字段取到 【学生详细信息表】 中的字段

1.1.2 关联字段不在的表 【学生详细信息表】

学生详细信息表模型类.objects.create(字段名=字段值, 字段名=字段值, ...)
根据字段类型及约束添加即可,无特别注意事项

1.2 一对多关系 【学生表 与 班级表】

1.2.1 关联字段所在的表 【学生表】的添加操作

学生表模型类.objects.create(字段名=字段值, 字段名=字段值, ...)
注:关联字段 stu_class 受【班级表】的 id 字段限制,添加时需保证该字段值在【班级表】中存在,且值不能重复

复制代码
关联字段:stu_class
	可通过该字段取到 【班级表】 中的字段

1.2.2 关联字段不在的表 【班级表】

班级表模型类.objects.create(字段名=字段值, 字段名=字段值, ...)
根据字段类型及约束添加即可,无特别注意事项

1.3 多对多关系 【学生表 与 课程表】 ==》 【stu_courses表】

这两张表根据字段类型及约束添加即可,无特别注意事项

但是,如果要在第三张表【stu_courses表】中添加数据,可这么干:

复制代码
获取 【学生表】模型类对象 stu
获取 【课程表】模型类对象 c1
获取 【课程表】模型类对象 c2
由于 stu_courses 在 【学生表】中,因此可通过 模型类对象.关联字段.add() 
	即 stu.stu_courses.add(c1, c2)

简而言之,就是通过 Student模型类对象 添加 多个 Courses模型类对象。

2 删除

2.1 一对一、一对多

2.1.1 关联字段所在的表的删除

随你删

2.1.2 关联字段不在的表的删除

由于设置了级联删除,也随你删

2.2 多对多

2.2.1 关联字段所在的表的删除

随你删

2.2.2 关联字段不在的表的删除

由于设置了级联删除,也随你删

2.2.3 第三张表的删除

【1】remove(id值)

复制代码
关联字段 stu_courses 所在的表 【学生表】
	获取 【学生表】模型类对象 stu
	获取 关联字段 调用 remove()
		即 stu.stu_courses.remove(课程id值)  ==》 删除指定学生指定课程编号的记录 

【2】clear()

复制代码
关联字段 stu_courses 所在的表 【学生表】
	获取 【学生表】模型类对象 stu
	获取 关联字段 调用 clear()
		即 stu.stu_courses.clear()  ==》 删除指定学生所有课程的记录 

3 修改

3.1 一对一、一对多

3.1.1修改关联字段所在的表

主要是关联字段的值修改后要保证该值在另一张表的对应字段值是存在的,

若一对多的关系还要保证修改后的值不能在该表中有重复值,

其余字段没什么特别注意的

3.1.2 修改关联字段不在的表

若是修改相关联的字段值,要保证该值在另一张表中不存在,否则可能会受影响

3.2 多对多

两张表的相关联字段的修改,要注意是否会对第三张表产生影响

3.2.1 对第三张表的修改

【1】set([n,m])

复制代码
关联字段 stu_courses 所在的表 【学生表】
	获取 【学生表】模型类对象 stu
	获取 关联字段 调用 set([课程id, 课程id, ...])
		即 stu.stu_courses.set([5, 8])  ==》先清空掉该生原有的课程,再重新添加编号5和8的课程 

4 查询

4.1 一对多 【学生表 和 班级表】

4.1.1 正向查询

通过 【有关联字段的表】的 【关联字段】即可 获得 【无关联字段的表】的对应的行记录

即 【"多"表 模型类对象 stu】调用 【关联字段 stu_class】,就可得到 【"一"表 对应的模型类对象 clazz】

复制代码
stu.stu_class ==> Clazz的模型类对象
stu.stu_class.class_name ==> 可通过 Clazz的模型类对象 获取相关字段,如 班级名称

4.1.2 反向查询

通过 【无关联字段的表】获取 【有关联字段的表】

即 通过 【"一"表 模型类对象 clazz】获取 【"多"表】对应的数据

【1】方式一
借助ORM内置的 "多"表表名_set

复制代码
clazz.students_set.all() --> 获取某班级的所有学生 ,返回QuerySet对象

【2】方式二
借助 在models.py定义模型类时,在设置关联字段所传入的参数 related_name 的值 students_list

复制代码
clazz.students_list.all()  --> 获取某班级的所有学生 ,返回QuerySet对象

4.2 一对一 【学生表 和 学生详细信息表】

4.2.1 正向查询

这个和 4.1.1 类似,不过多赘述

4.2.2 反向查询

通过 【无关联字段的表】的模型类对象 stu_info 获取 【有关联字段的表】对应的行记录

【1】方式一

借助 【有关联字段的表】的 小写表名 students

复制代码
stu_info.students --> 获取某个学生详细信息所对应的学生
stu_info.students.stu_name  --> 可通过 Students的模型类对象 获取相关字段,如 学生姓名

【2】方式二

借助 在models.py定义模型类时,在设置关联字段所传入的参数 related_name 的值 stu_list

复制代码
stu_info.stu_list   --> 获取某个学生详细信息所对应的学生
stu_info.stu_list.stu_name  --> 可通过 Students的模型类对象 获取相关字段,如 学生姓名

4.3 多对多 【学生表 和 课程表】

和 4.1 是一样的

复制代码
正向查询
	stu.stu_course.all()  --> 获取某学生的所有课程,返回QuerySet对象

反向查询
	【1】方式一
			course.student_set.all()  --> 获取某课程的所有学生,返回QueryS对象
	【2】方式二
			course.stu.all()   --> 获取某课程的所有学生,返回QueryS对象

5 高级查询【联表查询】

5.1 inner join 的形式

5.2 连续跨表查询

5.3 分组查询

5.4 分组后过滤 having的形式

5.5 排序查询

以上,无非就是借助 关联字段__字段名 或 related_name参数的值__字段名 进行操作

相关介绍,可移步:DJango 进行查看

相关推荐
AntBlack3 分钟前
Python : AI 太牛了 ,撸了两个 Markdown 阅读器 ,谈谈使用感受
前端·人工智能·后端
struggle202516 分钟前
Burn 开源程序是下一代深度学习框架,在灵活性、效率和可移植性方面毫不妥协
人工智能·python·深度学习·rust
腾飞开源20 分钟前
17_Flask部署到网络服务器
python·flask·python web开发·flask快速入门教程·flask框架·flask视频教程·flask会话技术
chanalbert26 分钟前
数据库连接池深度研究分析报告
数据库·spring
Mikhail_G34 分钟前
Python应用八股文
大数据·运维·开发语言·python·数据分析
mikes zhang35 分钟前
Flask文件上传与异常处理完全指南
后端·python·flask
烛阴1 小时前
深入浅出地理解Python元类【从入门到精通】
前端·python
Pitayafruit1 小时前
跟着大厂学架构01:如何利用开源方案,复刻B站那套“永不崩溃”的评论系统?
spring boot·分布式·后端
snpgroupcn1 小时前
泰国零售巨头 CJ Express 借助 SAP 内存数据库实现高效数据管理
数据库·express·零售
方圆想当图灵1 小时前
深入理解软件设计:领域驱动设计 DDD
后端·架构