Django query table to find Item that only exist in Parent field

Viewed 2387

I been struggling with doing a query to get the rows where a Item only exsist in Parnet field and not Child field.

This is the models.

class Item(models.Model):
    text = models.CharField()

class ItemRelations(models.Model):
    child = models.ForeignKey('Item', related_name='itemchild')
    parent = models.ForeignKey('Item', related_name='itemparent')

So I only want to filter out the Items that are not a child, but is a Parent. I call it the firstParent.

I tried so many different ways. I want to accomplish something like this.

firstParent = Item.objects.filter(ItemRelations_parent__is=self).exclude(ItemRelations_child__is=self)

Is it possible. Or does one have to make several queries and loops to manage this?

2 Answers

I'd suggest using the isnull filter for readability.

firstParent = Item.objects.filter(itemparent=self, itemchild__isnull=True)

In the specific example you've given in this comment, Item.pk is the attribute on the Item class. You want the item instance, not the class.

I believe, re-reading, that the question is:

Show the Item where the Item is a parent, but not a child. In that case:

firstParent = Item.objects.filter(itemparent__isnull=False, itemchild__isnull=True) will give you the queryset of objects that match that.

You may, subsequently wish to filter it further to match other aspects. Remember that django querysets are lazy. Don't confuse making several filters with making actual queries/database hits.

QuerySets are lazy – the act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated.

It is possible.

firstParent = Item.objects.exclude(child=self).filter(parent=self)

write exclude before filter.

Related