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 进行查看