过滤Django反向引用

时间:2016-11-23 14:24:46

标签: python django django-queryset

我正在尝试查询表中的所有对象,而没有来自其他模型的反向引用。

class A(models.Model):
    pass

class B(models.Model):
    reference = models.ForeignKey(A)

为了让所有A个对象都没有来自任何B个对象的引用,我做

A.objects.filter(b__isnull=True)

Django documentation on isnull根本没有提及反向引用。

我可以解决这个问题,还是记录得不好?

1 个答案:

答案 0 :(得分:2)

我使用相同的代码示例尝试使用Django 1.10.3。

让我们看一下Django创建的原始SQL语句:

>>> print(A.objects.filter(b__isnull=True).query)
SELECT "backrefs_a"."id" FROM "backrefs_a" LEFT OUTER JOIN "backrefs_b" ON ("backrefs_a"."id" = "backrefs_b"."reference_id") WHERE "backrefs_b"."id" IS NULL

从技术上讲,这不是Django将发送到数据库的完全相同的SQL,但它足够接近。有关更多讨论,请参阅https://stackoverflow.com/a/1074224/5044893

如果我们稍微了解一下,你会发现查询实际上非常安全:

SELECT "backrefs_a"."id"
FROM "backrefs_a"
LEFT OUTER JOIN "backrefs_b" ON ("backrefs_a"."id" = "backrefs_b"."reference_id")
WHERE "backrefs_b"."id" IS NULL

LEFT中的LEFT OUTER JOIN确保您将从A获取记录,即使B中没有匹配的记录。并且,因为Django不会使用{保存B {1}} id ,您可以放心,它会按照您的预期运作。