虽然我了解 Django 的 QuerySet 和延迟执行的高级思想,但我没有在 Django (3.1.2) 源代码中看到查询执行是如何触发的(即,数据库被命中)。例如,根据Django 文档 https://docs.djangoproject.com/en/3.1/topics/db/queries/#retrieving-a-single-object-with-get, get()
查询似乎立即命中数据库。但是查看源代码(django.db.models.query
):
def get(self, *args, **kwargs):
"""
Perform the query and return a single object matching the given
keyword arguments.
"""
clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
if self.query.can_filter() and not self.query.distinct_fields:
clone = clone.order_by()
limit = None
if not clone.query.select_for_update or connections[clone.db].features.supports_select_for_update_with_limit:
limit = MAX_GET_RESULTS
clone.query.set_limits(high=limit)
num = len(clone)
if num == 1:
return clone._result_cache[0]
if not num:
raise self.model.DoesNotExist(
"%s matching query does not exist." %
self.model._meta.object_name
)
raise self.model.MultipleObjectsReturned(
'get() returned more than one %s -- it returned %s!' % (
self.model._meta.object_name,
num if not limit or num < limit else 'more than %s' % (limit - 1),
)
)
我不知道在哪里clone
(这是一个QuerySet
对象)将其发送到数据库引擎query
(i.e., self._query
其中包含实际的Query
对象被解析为 SQL)并以某种方式将结果缓存在_result_cache
。事实上,当我尝试单步执行代码时,在某个时刻,self._result_cache
“神奇地”填充了查询结果。我从来没有接触过任何与 SQL 相关的代码,比如results_iter()
or execute_sql()
in django.db.models.sql.compiler
,我认为必须调用它才能与数据库后端交互?我的猜测是 Django 正在运行不同的进程/线程,而 PyCharm 仅单步执行主线程?如果是这种情况,有人可以指出一些相关的代码吗?我自己似乎无法从 Google 找到任何帮助。谢谢!
编辑:
通过查看代码我知道_fetch_all()
可以触发数据库命中,因为它连接到ModelIterable
,它执行 SQL 命令并将结果处理为 Python 对象,但为什么我从未涉足过这个方法?我想更好的问题是,什么时候_fetch_all()
曾经打过电话吗?
从您添加的代码中,看到这一行:
num = len(clone)
人们可以看到我们正在调用len
在查询集上。根据当查询集被评估时 - Django 文档 https://docs.djangoproject.com/en/3.1/ref/models/querysets/#when-querysets-are-evaluated:
len(). A QuerySet当您致电时进行评估len()在上面。正如您所期望的,这将返回结果列表的长度。
进一步展望源代码 - GitHub https://github.com/django/django/blob/f5a22442176878d07e80ae5ba0af1dd8d6910fbd/django/db/models/query.py#L261-L263 len
会打电话_fetch_all()
正如您正确假设的那样,结果来自:
def __len__(self):
self._fetch_all()
return len(self._result_cache)
上面引用的文档还指出了查询集何时被准确评估。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)