2

我有这两个简单的模型,A 和 B:

from django.db import models

class A(models.Model):
  name = models.CharField(max_length=10)

class B(A):
  age = models.IntegerField()

现在,我如何查询所有没有 B 实例的 A 实例?

我发现的唯一方法需要在每个子类上都有一个明确的唯一字段,该字段不为 NULL,以便我可以执行 A.objects.filter(b__this_is_a_b=None),例如,获取不是 B 实例的实例。我正在寻找一种方法来做到这一点,而无需添加这样的明确愚蠢的标志。

我也不想查询所有对象,然后在 Python 中过滤它们。我想让数据库为我做这件事,基本上就像SELECT * FROM A WHERE A.id in (SELECT id from B)

4

3 回答 3

2

由于某些版本的 django 或 python 这也适用:

A.Objects.all().filter(b__isnull=True)

因为如果 a 是 A 对象,当 a 存在时,ab 给出 a 的子类 B

我知道这是一个老问题,但我的回答可能会对这个主题的新搜索者有所帮助。

也可以看看:

多表继承

我自己对此的一个问题是:将超类向下转换为子类

于 2012-05-30T20:50:32.813 回答
1

我不确定是否可以在单个查询中使用 Django 的 ORM 纯粹在数据库中执行此操作。这是我能做到的最好的:

A.objects.exclude(id__in=[r[0] for r in B.objects.values_list("a_ptr_id")])

这是 2 个 DB 查询,最适合使用简单的继承图 - A 的每个子类都需要一个新的数据库查询。


好的,这需要大量的试验和错误,但我有一个解决方案。它非常丑陋,而且 SQL 可能比只使用两个查询更糟糕,但你可以这样做:

A.objects.exclude(b__age__isnull=True).exclude(b__age_isnull=False)

如果不引用 b 上的字段,就无法让 Django 进行连接。但是通过这些连续.exclude()的 s,您可以使任何具有 B 子类的 A 匹配一个或另一个排除项。剩下的就是没有 B 子类的 A。

无论如何,这是一个有趣的用例,你应该在 django-dev 上提出它......

于 2009-02-26T15:57:12.983 回答
0

我不使用 django,但看起来你想要 isinstance(obj, type) 内置 python 方法。

编辑:
A.objects.exclude(id__exact=B__id) 会工作吗?

于 2009-02-26T14:31:35.077 回答