Django何时确切运行查询? [英] When Exactly does Django Run the Query?

查看:66
本文介绍了Django何时确切运行查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然我了解Django的QuerySet和延迟执行的高级概念,但我在Django(3.1.2)的源代码中看不到如何触发查询执行(即,数据库被命中).例如,根据Django文档 get()查询似乎立即访问了数据库.但是查看源代码( django.db.models.query ):

While I understand the high-level ideas of Django's QuerySet and lazy execution, I don't see in Django (3.1.2) source code how query execution is triggered (i.e., database is being hit). For example, according to Django documentation, get() query seems to hit the database immediately. But looking at the source code (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 (即> self._query 包含要解析为SQL的实际 Query 对象),并以某种方式将结果缓存在 _result_cache 中.实际上,当我尝试单步执行代码时,有时 self._result_cache 神奇地"出现在代码中.填充了查询结果.我从未涉足任何与SQL相关的代码,例如django.db.models.sql.compiler 中的 results_iter() execute_sql()我认为必须调用哪个才能与数据库后端进行交互?我的猜测是Django正在运行不同的进程/线程,而PyCharm仅一步步穿过主线程吗?如果是这样,有人可以指出一些相关的代码吗?我似乎无法从Google自己那里找到任何帮助.谢谢!

I don't see where clone (which is a QuerySet object) sends to the database engine its query (i.e., self._query that contains the actual Query object being parsed into SQL) and somehow caches the result in the _result_cache. In fact, when I tried to step through the code, at some point, self._result_cache "magically" got populated with query results. I never stepped into any SQL-related code, like results_iter() or execute_sql() in django.db.models.sql.compiler, which I assume must be called to interact with the database backend? My guess is that Django is running a different process/thread and PyCharm only steps through the main thread? If this is the case, can someone point out some relevant code? I can't seem to find any help from Google myself. Thanks!

通过查看代码,我知道 _fetch_all()可以触发数据库命中,因为它连接到 ModelIterable ,后者执行SQL命令并将结果处理为Python对象,但是怎么回事呢?我从未涉足这种方法吗?我猜对此更好的问题是,什么时候调用过 _fetch_all()?

I know from looking at the code that _fetch_all() can trigger database hits because it connects to ModelIterable, which executes SQL commands and processes the results into Python objects, but how come I never stepped into this method ever? I guess the better question for this is, when is _fetch_all() ever called?

推荐答案

从您添加的代码中,看到以下行:

From the code you have added, see this line:

num = len(clone)

可以看到我们正在查询集上调用 len .根据评估QuerySet时-Django docs:

One can see that we are calling len on a queryset. According to When QuerySets are evaluated - Django docs:

len().在您调用 len()时,会评估 QuerySet .如您所料,这将返回结果列表的长度.

len(). A QuerySet is evaluated when you call len() on it. This, as you might expect, returns the length of the result list.

进一步查看源代码代码-GitHub len 将调用 _fetch_all(),因为您正确地假设结果来自:

Looking further in the source code - GitHub len would call _fetch_all() as you had correctly assumed is where the results are coming from:

def __len__(self):
    self._fetch_all()
    return len(self._result_cache)

以上引用的文档还指出了何时准确评估查询集.

The above referred documentation also notes when exactly a queryset is evaluated.

这篇关于Django何时确切运行查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆