3

我正在尝试使用与防止 Django 进行过多查询相关的预取,但我无法使其适用于具有继承的模型。

问题是当我用继承遍历模型时,模型实例没有被缓存,并且发出了一个 SQL 查询。

我不确定这是 Django 错误还是我以某种方式滥用它。

这是我的代码:

模型.py:

class ParentBase(models.Model): pass

class Parent(models.Model): pass

class ParentWithBase(ParentBase): pass

class Child(models.Model):
    parent = models.ForeignKey('Parent')
    parent_with_base = models.ForeignKey('ParentWithBase')

测试用例:

def test_prefetch_error(self):
    Child.objects.create(parent = Parent.objects.create(), parent_with_base = ParentWithBase.objects.create())
    child = Child.objects.prefetch_related('parent','parent_with_base').all()[0]
        with self.assertNumQueries(0):
            child.parent # This works just fine - no queries are emitted
        with self.assertNumQueries(0):
            child.parent_with_base # TEST FAILS HERE - since one query is emitted
4

1 回答 1

0

根据https://code.djangoproject.com/ticket/19420,它不缓存此结果的事实已在 Django 1.5 中得到修复。

但在这种情况下,您可以简单地使用select_related而不是prefetch_related. 如果您只是将其中一个替换为另一个,则您的测试通过。

select_related遵循外键关系。prefetch_related当您有多对多和多对一关系时更有用,因为它对每个关系进行单独的查找,然后在 Python 中进行“连接”。Usingselect_related只会使用连接进行一次数据库调用,但prefetch_related会立即进行多次调用,因为它假定它必须做它的事情。

于 2013-04-23T11:43:06.450 回答