【问题标题】:How can I query a model by if there is a subclass instance?如果有子类实例,如何查询模型?
【发布时间】:2010-10-10 02:12:18
【问题描述】:

我有这两个简单的模型,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)

【问题讨论】:

  • WHERE A.id not in (SELECT...),我想?

标签: python django model-inheritance


【解决方案1】:

由于某些版本的 django 或 python 也可以:

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

因为如果 a 是一个 A 对象 a.b 在它存在时给出 a 的子类 B

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

另见:

multi table inheritance

还有一个我自己的问题:downcasting a super class to a sub class

【讨论】:

    【解决方案2】:

    我不确定是否可以使用 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)
    

    没有办法让 Django 在不引用 b上的字段。但是有了这些连续的.exclude()s,你就可以 any A 与 B 子类匹配一个或另一个排除项。你只剩下A了 没有 B 子类。

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

    【讨论】:

    • 我会接受这个答案,但从某种意义上说,似乎任何答案都不是真正“正确”的。我会按照你的建议用 django-dev 提出来。
    【解决方案3】:

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

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

    【讨论】:

    • 不幸的是,没有。我正在尝试为 django ORM 提供正确的指令来生成 SQL 来为我执行此操作,而不是在客户端过滤它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-01
    • 2015-06-17
    • 2015-01-09
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多