Django 使用 select_related() 仍然访问 MySQL?

1 投票
3 回答
644 浏览
提问于 2025-04-15 13:55

我正在尝试优化一个相对较小的Django应用程序中的数据库调用。目前我有几个模型,分别是InquiryInquiryStatus。当我从MySQL中选择所有记录时,我得到了一个很好的JOIN语句,这个语句连接了两个表,但接下来却有很多请求去访问InquiryStatus表。即使我已经使用了select_related(),为什么Django还会发出单独的请求呢?

模型大致长这样:

class InquiryStatus(models.Model):
    status = models.CharField(max_length=25) 
    status_short = models.CharField(max_length=5)
    class Meta:
        ordering = ["-default_status", "status", "status_short"]

class Inquiry(models.Model):
    ts = models.DateTimeField(auto_now_add=True)
    type = models.CharField(max_length=50) 
    status = models.ForeignKey(InquiryStatus)
    class Meta:
        ordering = ["-ts"]

我为了调试写的视图大致长这样:

def inquiries_list(request, template_name="inquiries/list_inquiries.js"):
    ## Notice the "print" on the following line.  Forces evaluation.
    print models.Inquiry.objects.select_related('status').all()
    return HttpResponse("CRAPSTICKS")

我尝试使用select_related(depth=1),但没有任何变化。每个多余的数据库请求都是在WHERE子句中选择一个特定的id

更新:

有一段非常重要的代码应该放在模型中:

from fullhistory import register_model
register_model(Inquiry)
register_model(InquiryStatus)

结果是,fullhistory(出于我无法理解的原因)在获取每个单独的结果并进行解析。

3 个回答

0

你展示的代码其实不会生成任何查询。QuerySets(查询集)只有在需要的时候才会被计算,而不是在定义的时候。因为你没有在任何地方使用这个值,所以它不会被执行。

请给我们看看一个模板或者其他代码,这些代码实际上会对这个查询集进行计算,比如切片、遍历、打印,或者其他操作。

0

我觉得这和“懒惰求值”有关。Django 只有在必要的时候才会去访问数据库,而不是在你调用模型的时候就去访问。例如,当你使用 Inquiry.objects.select_related('status').all() 这个命令时,Django 可能会等到真正需要数据的时候才去查询数据库。

http://docs.djangoproject.com/en/dev/topics/db/queries/#id3

0

看起来 fullhistory 最终会把对象进行序列化,这个过程会检查实例中的每个字段,以便给它一个比较的基础。

你可以看看 get_all_data 这个函数:

http://code.google.com/p/fullhistory/source/browse/trunk/fullhistory/fullhistory.py

如果有人想详细解释一下为什么会这样,我会很乐意把那个答案标记为正确。

撰写回答