多对多表关系详解

一、前言

下面的讲解都基于三张表:student(学生表)、course(课程表)、student_course(学生课程中间表);

功能描述:有多个学生和多门课程,一个学生可以选修多门课程。

它们的表结构如下:

             student 学生表

字段                                  说明

id                                       学生id

student_name                   学生的姓名

course                               学生选修的课程(多对多)

               course 课程表

字段                                   说明

id                                      课程id

course_name                   课程名

二、创建多对多关系表

1. 自动创建

1)通过django的ORM迁移功能可以方便自动的建立多对多关系:

from django.dbimport models

    class Course(models.Model):

    id = models.AutoField(primary_key=True)

    course_name = models.CharField(max_length=100)

class Student(models.Model):

    id = models.AutoField(primary_key=True)

    student_name = models.CharField(max_length=100)

    course = models.ManyToManyField(to=Course)

2)在项目目录下,依次执行如下迁移命令:

python manage.py makemigrations

python manage.py migrate

3)迁移成功的话,就可以在数据库中看到这三张表了:


2. 手动创建

删除student表的manyTomany字段,然后手动创建中间表的orm模型即可:

class Course(models.Model):

    id = models.AutoField(primary_key=True)

    course_name = models.CharField(max_length=100)

    class Meta:

        db_table ='course'

class Student(models.Model):

    id = models.AutoField(primary_key=True)

    student_name = models.CharField(max_length=100)

    class Meta:

        db_table ='student'

class StudentAndCourse(models.Model):

    id = models.AutoField(primary_key=True)

    student = models.ForeignKey(to=Student, on_delete=models.DO_NOTHING)

    course = models.ForeignKey(to=Course, on_delete=models.DO_NOTHING)

    class Meta:

        db_table ='student_and_course'

三、多对多的使用

1. 前期准备

我们先为学生表创建一个学生,姓名为:曲鸟,学生ID为:1


2. 添加多对多数据及关系

1)创建单个新数据并建立关系

添加一个名为语文的课程并与曲鸟建立多对多的关系:

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生student.course.create(course_name="语文")# 创建名为语文的课程并建立关系

通过上面的代码可以看出,只要student是模型的Student对象,就可以直接创建数据并建立关系,所以将之前查询学生的代码:

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生,改为下面这样也是可以的:

student=Student.objects.filter(id=1).first()# 先通过学生id找到曲鸟这个学生

当然,新创建一个学生再新建课程进行关联也是可以的:

student=Student.objects.create(student_name="张三")# 创建名为张三的学生student.course.create(course_name="数学")# 创建名为数学的课程并建立关系


2)创建多个新数据并建立关系

如果直接使用批量添加数据(bulk_create)方法,是无法建立多对多的关系的。

如果非要批量创建并建立关系的话,可以再批量创建数据的时候指定主键值,然后通过set方法进行关联:

student = Student.objects.filter(id=1).first()

set_list = []

a = 7

for name in ['体育', '美术']:

    set_list.append(Course(course_name=name, id=a))# 手动指定id

    a +=1

set_list结果:[<Course: Course object (7)>, <Course: Course object (8)>]

aa = student.course.bulk_create(set_list)# 返回给aa的是一个列表,里面的元素为Course对象

aa结果:[<Course: Course object (7)>, <Course: Course object (8)>]

student.course.set(aa)# 通过set方法进行关联关系的建立


3)多对多建立关系add和set的区别

3.1 add

add接收一个Model对象,用于在原来存在的关系上进行单条多对多关系的建立(如果add的多对多关系原来已经存在了,则保持不变)

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生              course=Course.objects.get(id=7)# 查询id=7的课程                                                      student.course.add(course)

如果想基于原来存在的关系,批量增加新的多对多关系,则可以这样写:

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生                      course=Course.objects.all()# 查询所有课程                                                         student.course.add(*course)#注意加*号


3.2 set

set接收一个List,List里面的元素为Model对象,用于多条记录的多对多关系建立(如果已经存在了多对多关系,则会删除原来的关系,重新进行建立)

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生                course=Course.objects.all()# 查询所有课程                                                          student.course.set(course)


3. 删除多对多数据及关系

1)仅删除关系

1.1 删除单个关系

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生               course=student.course.get(id=7)                                                                        student.course.remove(course)

1.2 删除部分关系

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生       course=student.course.filter(id__in=[6,7])                                                            student.course.remove(*course)

1.3 删除所有关系

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生                                  student.course.clear()


2)删除关系并删除数据

2.1 删除单个

student=Student.objects.get(id=1)# 先通过学生id找到曲鸟这个学生          student.course.filter(id=6).delete()

2.2 删除部分

student.course.filter(id__in=[6,7]).delete()

2.3 删除所有

student.course.all().delete()


4. 修改多对多数据及关系

可以通过上面讲的新增关系和删除关系相结合进行修改的操作。


5. 查询多对多数据及关系

1. 正向查询

查询所有

student.course.all()

因为它就是model对象,所以所有model使用的ORM关键字都可以使用例如:filter、values等,这里不再举例。


2. 反向查询

例如想通过课程去查有哪些学生选修了,在查询时加入set关键字即可:

course=Course.objects.get(id=1)                                                                           data=course.student_set.all()#加入set关键字                                                                                print(data)

输出结果

<QuerySet[<Student:Studentobject(1)>]>

注:对于上面讲的增加、修改、删除中,也同样可以使用反向查询进行操作

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容