I have the following two Django models:
class Parent(models.Model):
name = models.CharField(max_length=50)
children = models.ManyToManyField("Child", through="ParentChild")
def __str__(self):
return self.name
class Child(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
Let's say I have four Parent objects in my database, only two of which have children:
for parent in Parent.objects.all():
print(parent, parent.children.count())
# Parent1 3
# Parent2 0
# Parent3 0
# Parent4 1
My goal is to write an efficient database query to fetch all parents that have at least one child. In reality, I have millions of objects so I need this to be as efficient as possible. So far, I've come up with the following solutions:
- Using
prefetch_related
for parent in Parent.objects.prefetch_related("children"):
if parent.children.exists():
print(parent)
# Parent1
# Parent4
- Using
filter:
for parent in Parent.objects.filter(children__isnull=False).distinct():
print(parent)
# Parent1
# Parent4
- Using
exclude:
for parent in Parent.objects.exclude(children__isnull=True):
print(parent)
# Parent1
# Parent4
- Using
annotateandexclude:
for parent in Parent.objects.annotate(children_count=Count("children")).exclude(children_count=0):
print(parent)
# Parent1
# Parent4
Which of these solutions is the fastest? Is there another approach that's even faster / more readable? I'm seeing a django Exists function but it doesn't appear to be applicable for this use case.