1

我想尽量减少我的应用程序进行的数据库查询的数量,并且我更熟悉 Django 的 ORM。我想知道,执行查询的情况是什么。

例如,这种格式符合我正在寻找的答案(例如目的,据我所知不准确):

  • 模型.objects.get()
    • 始终启动查询
  • 模型.objects.filter()
    • 仅在对象为空时启动查询
  • (...)

我假设 curried 过滤器操作永远不会发出额外的请求,但从文档看来,如果 filter() 是第一个调用的,它确实会发出数据库请求。

4

2 回答 2

2

请参阅 Django 关于何时评估查询集的文档:https ://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets-are-evaluated

在这种情况下,评估意味着执行查询。这主要发生在您尝试访问结果时,例如。当调用它list()len()迭代结果时。

get()在您的示例中,不返回查询集而是返回模型对象,因此会立即对其进行评估。

于 2013-05-26T00:30:35.213 回答
2

如果您正在使用测试用例,您可以使用 django 中包含的这个自定义断言TestCaseassertNumQueries()

例子:

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在您的测试用例中使用。

于 2013-05-26T00:45:42.347 回答