only和defer与select_related和prefetch_Related(面试重点)
这是面试常问点
only 和 defer
only
#res = models.Book.objects.all()
#res = models.Book.objects.values('title')
res = models.Book.objects.only('title')
for r in res:
print(r.title)
#print(r.price)
我们想要查询数据的时候,会用 all ,拿到所有对象,并且所有的字段都在对象里面。
当我们想要查询某个字段的时候,会用 values 或者values_list这两兄弟。
values查询出来的是一个字典,当我们想要用 点属性的形式点出来,就不能用values了。
这时候要用only。
上面的代码中,我们打印 r.title ,循环对象打印,这里一共会查询几次数据库? 一次!
当我们查询 r.price时,查询几次?有几个对象就查询几次。
总结:only会将括号内的字段对应的值 直接封装到返回给你的对象中 点该字段 不需要再走数据库一旦你点了不是括号内的字段 就会频繁的去走数据库查询
defer
和 only相反,defer会将括号内的字段排除之外将其他字段对应的值 直接封装到返回给你的对象中 点该其他字段 不需要再走数据库一旦你点了括号内的字段 就会频繁的去走数据库查询
select_related 和 prefetch_related
select_related
res = models.Book.objects.select_related('publish')
res1 = models.Author.objects.select_related('author_detail')
# res = models.Book.objects.all()
for r in res1:
print(r.author_detail)
print(r.author_detail.phone)
print(r.author_detail.addr)
上面代码查询几次数据库? 一次。
总结:
select_related 会自动帮你做连表操作 然后将连表之后的数据全部查询出来封装给对象
select_related括号内只能放外键字段
并且多对多字段不能放,因为多对多存在第三张表,他没办法通过第三个表去连表。会直接报错。
如果括号内外键字段所关联的表中还有外键字段 还可以继续连表
select_related(外键字段__外键字段__外键字段...)
相当于两张表变成了一个表,然后所有的数据都存在了对象里面。一次查询就全部拿到了。
prefetch_related
res = models.Book.objects.prefetch_related('publish')
# print(res)
for r in res:
print(r.publish.name)
总结:
prefetch_related 看似连表操作 其实是类似于子查询
prefetch_related括号内只能放外键字段
并且多对多字段不能放
如果括号内外键字段所关联的表中还有外键字段 还可以继续连表
select_related(外键字段__外键字段__外键字段...)
补一个点(不是面试的)
django中如何开启事务
导入一个模块
from django.db import transaction
with transaction.atomic():
在这里写的orm语句属于同一个事务,不用写什么提交,回滚之类的。
缩进出来之后自动结束事务