Django ORM QuerySet lazy loading(懒加载) 是如何实现的?原理为何?

2017-07-08 13:03:25 +08:00
 Veigar
比如说  books = Book.objects.all()
这一行代码并不会在运行时就取出所有数据
而是要到真正使用 books 时才会去取出数据
怎么做到的呢?原理是什么?
4295 次点击
所在节点    Python
5 条回复
ss098
2017-07-08 16:25:45 +08:00
可能是魔术方法。
SP00F
2017-07-08 23:32:24 +08:00
Django 不熟,是异步吗 ……
Morriaty
2017-07-11 13:26:58 +08:00
没看过源码,我想到的一种可能实现是:
1、all()只是编译好了 sql,但没执行
2、orm object 的__iter__()方法才是真执行 sql

大致逻辑:

class ORMObject(object):
def all(self):
self.sql = ....
return self

def filter(self, condition):
self.sql = ....
return self

def __iter__(self):
self.execute()
Morriaty
2017-07-11 13:27:57 +08:00
哇 v 站评论不支持 markdown 也就罢了,还自动删减空格.........
daya0576
2017-07-12 01:13:05 +08:00
楼上正解, 在执行这些魔术方法的时候去执行的 sql 并生成缓存:
Iteration, ie. 对 Queryset 进行 For 循环的操作.
slicing, e.g. Entry.objects.all()[:5], 获取 queryset 中的前五个对象, 相当于 sql 中的 LIMIT 5
picling/caching
repr/str
len (Note: 如果你只想知道这个 queryset 结果的长度的话, 最高效的还是在数据库的层级调用 count()方法, 也就是 sql 中的 COUNT(). )
list()
bool()

但调 queryset[5], values_list(), iterator()也会触发执行 sql, 但没有 cache 生成。

参考我的笔记: https://changchen.me/blog/20170503/django-performance-and-optimisation/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/373920

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX