In example. If I have a model Person who's got a mother field, which is a foreign key.. The following 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.
pk is short for primary key, which is a unique identifier for each record in a database. Every Django model has a field which serves as its primary key, and whatever other name it has, it can also be referred to as "pk".
One of the most powerful features of Django is its Object-Relational Mapper (ORM), which enables you to interact with your database, like you would with SQL. In fact, Django's ORM is just a pythonical way to create SQL to query and manipulate your database and get results in a pythonic fashion.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With