Shellbye.github.io icon indicating copy to clipboard operation
Shellbye.github.io copied to clipboard

Django related_name prefetch_related 浅析

Open Shellbye opened this issue 6 years ago • 0 comments

1.related_name

首先是related_name官网是这么说明的:

The name to use for the relation from the related object back to this one.

这个名字是用来反向查找与其有关的对象时使用的

我看过好几次,但是一直没搞明白是啥,知道实际再别人的代码看到具体的使用,才明白。举例说假设你有如下的models.py文件,用来定义老师与学生:

class Teacher(models.Model):
    name = models.CharField(max_length=50)

class Student(models.Model):
    name = models.CharField(max_length=50)
    tch = models.ForeignKey(Teacher, on_delete=models.SET_NULL, null=True)

通过学生获取老师是比较直观的,

stu = Student.objects.get(id=1)
tch = stu.tch

反过来要通过老师获取学生,Django官方有相应的操作,但是不是特别直观,

tch = Teacher.objects.get(id=1)
students = tch.student_set.all()

这样的有一个问题就是当一个学生表里有多个老师的外健时,如下:

class Student(models.Model):
    name = models.CharField(max_length=50)
    tch = models.ForeignKey(Teacher, on_delete=models.SET_NULL, null=True)
    headmaster = models.ForeignKey(Teacher, on_delete=models.SET_NULL, null=True)

这个反向查找就会报错,因为有两个外健,Django不知道在逆向查找时该找哪一个,这个时候就是related_name发挥作用的时候了:

class Student(models.Model):
    name = models.CharField(max_length=50)
    tch = models.ForeignKey(Teacher, on_delete=models.SET_NULL, null=True, related_name='class_stu')
    headmaster = models.ForeignKey(Teacher, on_delete=models.SET_NULL, null=True, related_name='school_stu')

这时,班级老师要查找学生就可以通过设置好的related_name进行了:

tch = Teacher.objects.get(id=1)
students = class_stu

而校长则是通过另一个来获取本校的所有学生

tch = Teacher.objects.get(id=1)
students = school_stu

2. prefetch_related

有了related_name,可以方便的反向查找与其关联的对象,但是因为要多次方法数据库,效率不够高,所以就有了prefetch_related

Shellbye avatar Jun 07 '18 06:06 Shellbye