ORM性能相关
数据库
class Student(models.Model):
name = models.CharField(max_length=32, verbose_name="姓名")
classes = models.ForeignKey('Classes', on_delete=models.CASCADE)
class Classes(models.Model):
name = models.CharField(max_length=32, verbose_name="班级")
当用对象跨表时,可见查询语句非常多
def index(request):
students = models.Student.objects.all()
for student in students:
print(student.classes)
(0.000) SELECT "app01_student"."id", "app01_student"."name", "app01_student"."classes_id" FROM "app01_student"; args=()
(0.000) SELECT "app01_classes"."id", "app01_classes"."name" FROM "app01_classes" WHERE "app01_classes"."id" = 1; args=(1,)
(0.000) SELECT "app01_classes"."id", "app01_classes"."name" FROM "app01_classes" WHERE "app01_classes"."id" = 2; args=(2,)
(0.000) SELECT "app01_classes"."id", "app01_classes"."name" FROM "app01_classes" WHERE "app01_classes"."id" = 3; args=(3,)
values字段查询
def index(request):
students = models.Student.objects.values('classes__name')
for student in students:
print(student)
SELECT "app01_classes"."name"
FROM "app01_student"
INNER JOIN "app01_classes"
ON ("app01_student"."classes_id" = "app01_classes"."id")
做了连表查询,只是把结果存在了字典,不必须使用对象时,可采用values加 字段查询。
select_related
def index(request):
students = models.Student.objects.all().select_related()#可加外键字段,实测作用一样
for student in students:
print(student.classes.name)
SELECT "app01_student"."id",
"app01_student"."name",
"app01_student"."classes_id",
"app01_classes"."id",
"app01_classes"."name"
FROM "app01_student"
INNER JOIN "app01_classes"
ON ("app01_student"."classes_id" = "app01_classes"."id")
这样也是做了连表查询,而且返回的仍然是对象。
prefetch_related
def index(request):
students = models.Student.objects.all().prefetch_related('classes')#要加外键在字段
for student in students:
print(student.classes.name)
SELECT "app01_student"."id",
"app01_student"."name",
"app01_student"."classes_id"
FROM "app01_student"
SELECT "app01_classes"."id",
"app01_classes"."name"
FROM "app01_classes"
WHERE "app01_classes"."id" IN ('1', '2', '3')
可见做了子查询,返回结果也是对象。
only
def index(request):
students = models.Student.objects.all().only('name')
for student in students:
print(student.name)
SELECT "app01_student"."id",
"app01_student"."name"
FROM "app01_student"
only只查某些 字段,与其相反的有个defer,不再举例。
小结
-
尽量不查对象,能用values()就用values
-
select_related('classes') 连表查询 多对一 一对一
-
prefetch_related('classes') 子查询 多对一 多对多
-
only('name') 指定某些字段 defer 指定排除某些字段