Django MPTT queryset for instances with children with a certain attribute

1.6k views Asked by At

I'm using Django MPTT, with the model Foobar like this:

class Foobar(MPTTModel):
     parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

If I want to select all Foobars with children, I can do this:

[x for x in Foobar.objects.all() if x.get_children().exists()]

If I want to select all Foobars that have children with a certain attribute (like published), I can do this:

[x for x in Foobar.objects.all() if x.get_children().filter(published=True).exists()]

I can't work out a way to do this in one query, though. I need to do it in one query in order to be able to use it for the limit_choices_to argument of ForeignKey:

class Example(models.Model):
    related_foobar = models.ForeignKey(
        Foobar,
        limit_choices_to=Q(....), # How do I make this work?
    )
1

There are 1 answers

0
user2390182 On

Well, the pure property of being a parent is filtered for via the __isnull filter. This generally holds for reverse foreign key testing:

Foobar.objects.filter(children__isnull=False)  # must have children

It should be mentioned that 'children' in this query is the related_query_name of the ForeignKey. This defaults to the related_name if that is provided or to the lowercase model name (foobar in this case).

With a concrete child property, you can simply do:

Foobar.objects.filter(children__published=True)

This will only include Foobars with at least one child that is published.