In SQL, the placement of a condition, whether in the ON clause or the WHERE clause, can affect the results. filter()
in Django seems to put conditions in the WHERE clause.
Say I have these models:
class Nations(models.Model):
deleted = models.BooleanField(default=False)
class People(models.Model):
nation = models.ForeignKey(Nations, on_delete=models.CASCADE)
deleted = models.BooleanField(default=False)
And I want to find the nations with no people in them, I could do:
SELECT nations.id, nations.deleted
FROM nations
LEFT JOIN people
ON people.nation_id = nations.id
WHERE people.id IS NULL;
But let's say people can be soft deleted, and I want to find nations with no undeleted people in them. I would do:
SELECT nations.id, nations.deleted
FROM nations
LEFT JOIN people
ON people.nation_id = nations.id
AND people.deleted IS FALSE
WHERE people.id IS NULL;
However, in Django, if I do:
Nations.objects.filter(people__id__isnull=True, people__deleted=False)
This is equaivalent to the query:
SELECT nations.id, nations.deleted
FROM nations
LEFT JOIN people
ON people.nation_id = nations.id
WHERE people.id IS NULL
AND people.deleted IS FALSE;
Unlike the desired query, this will not include nations that have deleted people only! How can I get Django to move the soft delete check into the ON clause?