以下代码是否在每次调用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
我的观点包含一系列问题和用户回复,并在工作表中得分。我的目标是在不返回数据库的情况下执行所有评分,然后使用后台任务保存我的比较结果(字典),如果需要更长时间则可以。我想消除任何不必要的数据库命中。
答案 0 :(得分:0)
嗯,你的问题不清楚,但有一点可以肯定,至少需要对数据库进行一次点击。实际上,在您的代码示例中使用:
question_name = question.name
但如果question
事先不是Question
型号的实例,我就不会看到这种情况。
因此,考虑到您从查询创建实例时对数据库的初始命中,question_name
可以根据需要随时重复使用,而无需访问数据库。请将此视为数据库行的静态实例。
修改强>
现在进行编辑,这是不一样的行为。要正确理解幕后发生的事情,你需要理解"懒惰"的概念。事实上,由于查询集在Django中是懒惰的,所以这一行:
questions = Question.objects.filter(test=some_test)
不会导致数据库受到任何影响。 Querysets代表SQL查询集。因此,此时,由于您没有要求从数据库中获取某些内容,因此尚未对其进行实际评估。这是想要的行为,因为它确保仅在需要时访问数据库。正如documentation所述,这里是评估查询集的情况:
<强> 迭代 强>
QuerySet是可迭代的,它首先执行其数据库查询 你迭代它的时间。
<强> 切片 强>
对未评估的QuerySet进行切片通常会返回另一个未评估的QuerySet QuerySet,但是如果你使用的话,Django会执行数据库查询 切片语法的“step”参数,并将返回一个列表。切片 已评估的QuerySet也返回一个列表。
<强> 酸洗/缓存 强>
再版()。在对它调用repr()时会评估QuerySet。这是 为了方便Python交互式解释器,你可以 在交互使用API时立即看到您的结果。
LEN()。在您上面调用len()时会评估QuerySet。就像你一样 可能期望,返回结果列表的长度。
列表()。通过调用list()来强制评估QuerySet
BOOL()。在布尔上下文中测试QuerySet,例如使用bool(), 或者,或者if语句将导致查询被执行
因此,您可以看到情况1适用于您的特定情况。迭代将导致数据库命中。