我想尽量减少我的应用程序进行的数据库查询的数量,并且我更熟悉 Django 的 ORM。我想知道,执行查询的情况是什么。
例如,这种格式符合我正在寻找的答案(例如目的,据我所知不准确):
- 模型.objects.get()
- 始终启动查询
- 模型.objects.filter()
- 仅在对象为空时启动查询
- (...)
我假设 curried 过滤器操作永远不会发出额外的请求,但从文档看来,如果 filter() 是第一个调用的,它确实会发出数据库请求。
请参阅 Django 关于何时评估查询集的文档:https ://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets-are-evaluated
在这种情况下,评估意味着执行查询。这主要发生在您尝试访问结果时,例如。当调用它list()
或len()
迭代结果时。
get()
在您的示例中,不返回查询集而是返回模型对象,因此会立即对其进行评估。
如果您正在使用测试用例,您可以使用 django 中包含的这个自定义断言TestCase
:assertNumQueries()。
例子:
with self.assertNumQueries(2):
x = SomeModel.objects.get(pk=1)
y = x.some_foreign_key_in_object
如果预期的查询数有误,您会看到以下形式的断言失败消息:
Num queries (expected - actual):
2 : 5
在此示例中,即使没有明确的查询(获取、过滤、排除等),外键也会导致额外的查询。
出于这个原因,我会使用一种实用的方法:测试或记录,而不是尝试了解 django 应该查询的每种情况。
如果您不使用单元测试,您可以使用打印 django 发送的实际 SQL 语句的其他方法,这样您就可以了解查询的复杂性,而不仅仅是查询的数量:
(DEBUG
设置必须设置为True
)
from django.db import connection
x = SomeModel.objects.get(pk=1)
y = x.some_foreign_key_in_object
print connection.queries
打印将显示查询字典:
[
{'sql': 'SELECT a, b, c, d ... FROM app_some_model', 'time': '0.002'},
{'sql': 'SELECT j, k, ... FROM app_referenced_model JOIN ... blabla ',
'time': '0.004'}
]
上的文档connection.queries
。
当然,您也可以结合这两种方法并print connection.queries
在您的测试用例中使用。