I have these two simple models, A and B:
我有两个简单的模型,A和B:
from django.db import models
class A(models.Model):
name = models.CharField(max_length=10)
class B(A):
age = models.IntegerField()
Now, how can I query for all instances of A which do not have an instance of B?
现在,我如何查询一个没有B实例的所有实例?
The only way I found requires an explicitly unique field on each subclass, which is NOT NULL, so that I can do A.objects.filter(b__this_is_a_b=None), for example, to get instances that are not also B instances. I'm looking for a way to do this without adding an explicit silly flag like that.
我发现的惟一方法是在每个子类上显式地设置唯一的字段,这不是NULL,这样我就可以做A.objects.filter(b__this_is_a_b=None),例如,获取不属于B实例的实例。我在寻找一种方法来做到这一点,而不需要添加一个明显的愚蠢的标志。
I also don't want to query for all of the objects and then filter them in Python. I want to get the DB to do it for me, which is basically something like SELECT * FROM A WHERE A.id in (SELECT id from B)
我也不想查询所有的对象,然后用Python来过滤它们。我想让DB为我做,这基本上是像SELECT * FROM A。id(从B中选择id)
3 个解决方案
#1
2
Since some version of django or python this works as well:
因为django或python的某些版本同样适用:
A.Objects.all().filter(b__isnull=True)
because if a is an A object a.b gives the subclass B of a when it exists
因为a是a物体。b在存在的时候给出a的子类b。
I Know this is an old question, but my answer might help new searchers on this subject.
我知道这是一个老问题,但我的回答可能会帮助新的搜索者在这个问题上。
see also:
参见:
多表继承
And one of my own questions about this: downcasting a super class to a sub class
我自己的一个问题是:将一个超类降级为一个子类。
#2
1
I'm not sure it's possible to do this purely in the DB with Django's ORM, in a single query. Here's the best I've been able to do:
我不确定是否可以在一个查询中使用Django的ORM来实现这一点。这是我能做的最好的事情:
A.objects.exclude(id__in=[r[0] for r in B.objects.values_list("a_ptr_id")])
This is 2 DB queries, and works best with a simplistic inheritance graph - each subclass of A would require a new database query.
这是两个DB查询,最好使用一个简单的继承图——每个子类都需要一个新的数据库查询。
Okay, it took a lot of trial and error, but I have a solution. It's ugly as all hell, and the SQL is probably worse than just going with two queries, but you can do something like so:
这需要很多的尝试和错误,但我有一个解决方案。它很丑,而且SQL可能比两个查询更糟糕,但是你可以这样做:
A.objects.exclude(b__age__isnull=True).exclude(b__age_isnull=False)
There's no way to get Django to do the join without referencing a field on b. But with these successive .exclude()
s, you make any A with a B subclass match one or the other of the excludes. All you're left with are A's without a B subclass.
如果没有引用b中的字段,就没有办法让Django执行join操作,但是使用这些连续的.exclude()s,您可以使任何a与b子类匹配一个或另一个不包含。只剩下A没有B子类。
Anyway, this is an interesting use case, you should bring it up on django-dev...
不管怎样,这是一个有趣的用例,你应该把它提上django-dev…
#3
0
I don't work with django, but it looks like you want the isinstance(obj, type) built-in python method.
我不使用django,但是看起来您想要的是isinstance(obj, type)内置的python方法。
Edit:
Would A.objects.exclude(id__exact=B__id) work?
编辑:A.objects.exclude(id__exact = B__id)工作?
#1
2
Since some version of django or python this works as well:
因为django或python的某些版本同样适用:
A.Objects.all().filter(b__isnull=True)
because if a is an A object a.b gives the subclass B of a when it exists
因为a是a物体。b在存在的时候给出a的子类b。
I Know this is an old question, but my answer might help new searchers on this subject.
我知道这是一个老问题,但我的回答可能会帮助新的搜索者在这个问题上。
see also:
参见:
多表继承
And one of my own questions about this: downcasting a super class to a sub class
我自己的一个问题是:将一个超类降级为一个子类。
#2
1
I'm not sure it's possible to do this purely in the DB with Django's ORM, in a single query. Here's the best I've been able to do:
我不确定是否可以在一个查询中使用Django的ORM来实现这一点。这是我能做的最好的事情:
A.objects.exclude(id__in=[r[0] for r in B.objects.values_list("a_ptr_id")])
This is 2 DB queries, and works best with a simplistic inheritance graph - each subclass of A would require a new database query.
这是两个DB查询,最好使用一个简单的继承图——每个子类都需要一个新的数据库查询。
Okay, it took a lot of trial and error, but I have a solution. It's ugly as all hell, and the SQL is probably worse than just going with two queries, but you can do something like so:
这需要很多的尝试和错误,但我有一个解决方案。它很丑,而且SQL可能比两个查询更糟糕,但是你可以这样做:
A.objects.exclude(b__age__isnull=True).exclude(b__age_isnull=False)
There's no way to get Django to do the join without referencing a field on b. But with these successive .exclude()
s, you make any A with a B subclass match one or the other of the excludes. All you're left with are A's without a B subclass.
如果没有引用b中的字段,就没有办法让Django执行join操作,但是使用这些连续的.exclude()s,您可以使任何a与b子类匹配一个或另一个不包含。只剩下A没有B子类。
Anyway, this is an interesting use case, you should bring it up on django-dev...
不管怎样,这是一个有趣的用例,你应该把它提上django-dev…
#3
0
I don't work with django, but it looks like you want the isinstance(obj, type) built-in python method.
我不使用django,但是看起来您想要的是isinstance(obj, type)内置的python方法。
Edit:
Would A.objects.exclude(id__exact=B__id) work?
编辑:A.objects.exclude(id__exact = B__id)工作?