开发者

Is there a way to resist unnecessary joins that are only checking id existence when using Django's orm?

In example. If I have a model Person who's got a mother field, which is a foreign key.. The follo开发者_如何学Cwing is getting to me:

p = Person.object.get(id=1)
if p.mother_id:
    print "I have a mother!"

In the above example, we've issued one query. I've tricked Django into not fetching the mother by using the _id field instead of mother.id. But if I was to filter on everyone who doesn't have a mother:

Person.objects.filter(mother=None)
Person.objects.filter(mother__id=None)
Person.objects.filter(mother__isnull=True)
Person.objects.filter(mother__id__isnull=True)

All of these join in the related table unnecessarily.. and I can't reference the _id columns, because they're not fields.. so either of the following fails:

Person.objects.filter(mother_id__isnull=True)
Person.objects.filter(mother_id=None)

Is there a way for me to build a querySet that checks the existence of a value in the foreign key column without incurring the join?

Thanks in advance.

Edit (answered): Credit goes to Bernd, who commented on Daniel's answer, but it turns out that this workaround does splendidly for returning people without mothers, without issuing the unnecessary join:

Person.objects.exclude(mother__isnull=False)

Edit (more detail):

I should also mention that I've found this behavior actually only seems to rear it's head when the FK relationship is nullable. Odd, but true.


I was surprised by this - I thought Person.object.filter(mother=None) would work without an extra join - but on checking it turns out you're right. In fact this has been logged as a bug in Django's ticket tracker.

Unfortunately, the person who logged it - and who (re)wrote most of the Django query code - is no longer actively contributing to Django, so I don't know when it will actually get fixed. You might try one of the patches on that ticket and see if they help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜