Django的ManyToManyField(多对多)讲解
Django的ManyToMany详解
一、前言
下面的讲解都基于三张表:student(学生表)
、course(课程表)
、student_course(学生课程中间表)
;
功能描述:有多个学生和多门课程,一个学生可以选修多门课程。
它们的表结构如下:
字段 | 说明 |
---|---|
id | 学生id |
student_name | 学生的姓名 |
course | 学生选修的课程(多对多) |
字段 | 说明 |
---|---|
id | 课程id |
course_name | 课程名 |
字段 | 说明 |
---|---|
id | 中间表id |
student_id | 学生id |
course_id | 课程id |
文章目录
二、创建多对多关系表
1. 自动创建
1)通过django的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)
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
aa = student.course.bulk_create(set_list) # 返回给aa的是一个列表,里面的元素为Course对象
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. 反向查询
例如想通过课程去查有哪些学生选修了,在查询时按model类名(全为小写)_set
填写关键字即可:
course=Course.objects.get(id=1)
data=course.student_set.all() #加入set关键字
print(data)
输出结果
<QuerySet [<Student: Student object (1)>]>
注:对于上面讲的增加、修改、删除中,也同样可以使用反向查询进行操作
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)