当我访问对象的属性时,Django 是否会访问数据库?

bks*_*sam 8 python django django-models

每次调用question.name时,以下代码是否都会查询数据库?

class Question(models.Model):
    name=models.CharField()
    test=models.ForeignKey(Test)

questions = Question.objects.filter(test=some_test)
for question in questions:
    question_name = question.name
Run Code Online (Sandbox Code Playgroud)

我的视图采用一组问题和用户响应并对工作表进行评分。我的目标是执行所有评分而不返回数据库,然后使用后台任务保存比较结果(字典),如果需要更长的时间也可以。我想消除任何不必要的数据库点击。

sch*_*tte 1

好吧,你的问题不清楚,但有一件事可以肯定,至少需要对数据库进行一次点击。事实上,在您的代码示例中您使用:

\n\n
question_name = question.name\n
Run Code Online (Sandbox Code Playgroud)\n\n

question但如果事先不是模型的实例,我认为这不起作用Question

\n\n

因此,考虑到您通过查询对数据库的初始命中来创建实例,question_name然后可以根据需要多次重复使用,而无需访问数据库。请注意,这是数据库行的静态实例。

\n\n

编辑

\n\n

现在对于您的编辑来说,这不是相同的行为。要正确理解幕后发生的事情,您需要理解“惰性”的概念。事实上,由于 Django 中的查询集是惰性的,所以这一行:

\n\n
questions = Question.objects.filter(test=some_test)\n
Run Code Online (Sandbox Code Playgroud)\n\n

不会对数据库造成任何影响。查询集代表 SQL 查询集。因此,此时,由于您没有要求从数据库中获取某些内容,所以实际上尚未对其进行评估。这是所需的行为,因为它确保仅在需要时才访问数据库。正如文档所述,这里是评估查询集的情况:

\n\n

迭代

\n\n
\n

QuerySet 是可迭代的,并且它会在您第一次迭代它时执行其数据库查询。

\n
\n\n

切片

\n\n
\n

对未计算的 QuerySet 进行切片通常会返回另一个未计算的 QuerySet,但如果使用切片语法的\n \xe2\x80\x9cstep\xe2\x80\x9d 参数,Django 将执行数据库查询,并返回一个列表。对已评估的 QuerySet 进行切片也会返回一个列表。

\n
\n\n

酸洗/缓存

\n\n
\n

代表()。当您对其调用 repr() 时,将对 QuerySet 进行评估。这是为了方便 Python 交互式解释器,以便您在交互使用 API 时可以立即看到结果。

\n\n

len()。当您对 QuerySet 调用 len() 时,就会对它进行求值。正如您可能期望的那样,这将返回结果列表的长度。

\n\n

列表()。通过调用 list() 来强制评估 QuerySet

\n\n

布尔()。在布尔上下文中测试 QuerySet,例如使用 bool()、\n or、and 或 if 语句将导致执行查询

\n
\n\n

因此,正如您所看到的,情况 1 适用于您的特定情况。迭代将导致对数据库的命中。

\n