0

For example I have this model:

class Parent(models.Model):
    name = models.CharField(max_length=255)


class Child(models.Model):
    parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
    value = models.IntegerField()
p1 = Parent.objects.create(name='parent1')
c1 = Child.objects.create(parent=p1, value=1)
c2 = Child.objects.create(parent=p1, value=2)
c3 = Child.objects.create(parent=p1, value=3)

I want to make a subquery to behave like this:

parents_with_children = Parent.objects.annotate(
    child_values=ArrayAgg('child__value', filter=F('child__parent_id') == F('id'))
)

for parent in parents_with_children:
    print(f"Parent: {parent.name}, Child Values: {parent.child_values}")
    
OUTPUT: ## Parent: parent1, Child Values: [1, 2, 3]

2 Answers 2

2

After trying googling and using ChatGPT I figured out how to solve this. Thanks!

child_values_subquery = Child.objects.filter(
    parent_id=OuterRef('id')
).values("parent_id").annotate(
    value_array=ArrayAgg('value')
).values('value_array')[:1]
parents_with_children = Parent.objects.annotate(
    child_values=Subquery(
        child_values_subquery,
        output_field=ArrayField(models.IntegerField())
    )
)
Sign up to request clarification or add additional context in comments.

Comments

1

How about below, your code is correct.

from django.contrib.postgres.aggregates import ArrayAgg


parents = Parent.objects.annotate(child_values=ArrayAgg("child__value"))

for parent in parents:
    print(parent, parent.child_values)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.