MarkD
MarkD

Reputation: 4954

Django- getting a list of foreign key objects

Lets say I have the following models:

class ParentModel(models.Model):
    name = models.CharField()
    child = models.ForeignKey("ChildModel")

class ChildModel(models.Model):
    name = models.CharField()

Now, given some filter on ParentModels, I want to retrieve a list of all children models. I have tried:

children = ParentModel.objects.filter(name__startswith='A').values_list('child', flat=True)

However this returns a list of ChildModel ids, rather than the full objects. Is there a queryset function that will accomplish what I am trying to do or do I need to write an additional filter query using the returned ids? I.e.- instead of:

children => [51L, 53L, 54L]

I want:

children => [<ChildModel: ChildModel Object>, <ChildModel: ChildModel Object>, <ChildModel: ChildModel Object>]

Upvotes: 17

Views: 29887

Answers (3)

Pablo Estrada
Pablo Estrada

Reputation: 3472

This one was an active issue on the Django site: https://code.djangoproject.com/ticket/8144

You have two options:

  1. Write your own queryset subclass
  2. Add another filter to get the object of your retreived ids

I know how to implement option 2, so here is my approach:

Option #2:

children_ids = ParentModel.objects.filter(name__startswith='A').values_list('child', flat=True)
children = ChildModel.objects.filter(pk__in=children_ids)

Upvotes: 5

rlfrahm
rlfrahm

Reputation: 359

I think you may want to refactor your models to be something like:

class ParentModel(models.Model):
    name = models.CharField()

class ChildModel(models.Model):
    name = models.CharField()
    parent = models.ForeignKey(ParentModel)

Then you can just do the following to receive a queryset list of ChildModel:

ParentModel.childmodel_set.all()

This would be interpreted as "each ParentModel can have many ChildModel's."

Upvotes: 6

Daniel Roseman
Daniel Roseman

Reputation: 600049

You can use a subquery with __in:

Child.objects.filter(parent__in=Parent.objects.filter(name__startswith='A'))

(Note, your naming is a bit odd here: usually the child is the one with the foreign key, since it assumes that a parent can have multiple children.)

Upvotes: 25

Related Questions