Django backwards relation

Question:

I am setting up webservices for an application and I have the following models:

class Parent(models.Model):
    ...
class Child(models.Model):
    parent = models.ForeignKey(Course)
    ...

The relation is One to Many (1 Parent, many Children)

Now, I would like to get all the Parent objects with its particular Child and send it as a JSON Request.

Is it possible to do so without having to first get all the "Childs" and iterate through them looking for the ones related to the particular parent?

I think that would be extremely inefficient for really large databases, plus the "Childs" won’t be repeated in other "Parents"

Thank you very much

Asked By: Alqueraf

||

Answers:

Why would you need to iterate? Even if Django didn’t provide you with a special backwards syntax, you could always do this:

Child.objects.filter(parent=my_parent)

but as a cursory Google for the title of your question would have shown, there is a special syntax for backwards relations:

my_parent.child_set.all()
Answered By: Daniel Roseman

Every relationship in Django automatically gets its reverse relation added to the model. In the case of a ForeignKey or ManyToManyField that relation contains several objects. In that case, the default attribute name is set to <model>_set, so in this case child_set. This is a manager and can be used as such, so e.g. to iterate over all children:

for child in parent.child_set.all():
    do_something()

You can also specify the attribute name used for the reverse relation using the related_name attribute:

class Child(models.Model):
    parent = models.ForeignKey(Parent, related_name='children')

for child in parent.children.filter(some_field=True):
    do_something()

Read more in the documentation on following relations backwards and how are backward relationships possible.

Answered By: knbk

Yes, in django you can use:

parentInstance.child_set.all()

where parentInstance is one particular parent in your Parent database. That will return all of the Child objects associated with it in an efficient manner. To make it a JSON response, you can try something like this:

import json

from django.http import HttpResponse

response_data = {}
response_data[str(parentInstance)] = parentInstance.child_set.all()
return HttpResponse(json.dumps(response_data), content_type="application/json"

adopted from here.

Answered By: rofls
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.