Django是一个支持多对多关系的Web框架,可以在模型中定义多对多关系。(话外:还有一个是SQLAlchemy:在SQLAlchemy中,你可以使用relationship()函数来定义多对多关系,并通过secondary参数指定中间表)
多对多关系通常涉及两个实体之间的复杂交互,例如用户和组之间的关系,或者课程和学生之间的关系。在Django中,可以使用ManyToManyField字段来定义多对多关系。
例如,我们可以定义一个名为Student的模型和一个名为Course的模型,并在它们之间建立多对多关系,如下所示:
class Student(models.Model):
name = models.CharField(max_length=50)
courses = models.ManyToManyField(Course)
class Course(models.Model):
name = models.CharField(max_length=50)
students = models.ManyToManyField(Student)
在上面的代码中,Student模型中的courses和Course模型中的students都是ManyToManyField字段,这意味着一个学生可以选择多个课程,而一个课程也可以拥有多个学生。
要在代码中创建多对多关系,可以使用add()、remove()、clear()和set()等方法进行操作。例如,可以使用以下代码将一个学生添加到一个课程中:
course = Course.objects.get(id=1)
student = Student.objects.get(id=1)
course.students.add(student)
上面的代码将学生添加到课程中,并创建一个关联记录,将学生和课程关联起来。可以使用类似的方法将一个学生从一个课程中删除:
course = Course.objects.get(id=1)
student = Student.objects.get(id=1)
course.students.remove(student)
此外,还可以使用额外的关联数据来存储有关关系的附加信息。例如,可以使用以下代码将一个学生与一个课程关联,并存储学生在该课程中的分数:
course = Course.objects.get(id=1)
student = Student.objects.get(id=1)
course.students.add(student, through_defaults={'score': 90})
上面的代码将学生与课程关联,并将分数存储在额外的关联数据中。要访问附加关联数据,可以使用through模型,例如:
class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
score = models.IntegerField()
class Student(models.Model):
name = models.CharField(max_length=50)
courses = models.ManyToManyField(Course, through=Enrollment)
class Course(models.Model):
name = models.CharField(max_length=50)
students = models.ManyToManyField(Student, through=Enrollment)
在上面的代码中,我们定义了一个名为Enrollment的模型,它保存学生与课程之间的关联数据,例如学生在该课程中的分数。然后,我们将Enrollment模型传递给ManyToManyField字段的through参数,以便在创建关联记录时将关联数据存储在Enrollment模型中。现在,我们可以使用以下代码访问学生在一个课程中的分数:
enrollment = Enrollment.objects.filter(student=student, course=course).first()
score = enrollment.score
使用prefetch_related()函数进行查询,减少查询的次数。
它是Django ORM提供的用于表关联查询时减少查询次数的一个函数。当我们查询一个Model时,如果和其他Model有外键或多对多关系,那么默认情况下,Django ORM会分别查询这些关联的Model,这样很容易出现查询次数过多的问题。prefetch_related()的作用是把需要查询的关联Model都一次性查询出来,可以有效减少查询次数,提高性能。
使用方法:使用prefetch_related()函数需要满足以下条件:当前Model必须有关联的其他Model必须有外键或多对多关系
下面是使用prefetch_related()函数的用法:
Student.objects.prefetch_related(‘enrollment__score’, …).values(‘enrollment__score’)
需要注意的是,prefetch_related()函数只能对关联的外键或多对多关系进行查询,不能对一对一关系进行查询。
prefetch_related()对应的SQL语句是inner join 联合查询