Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django backwards relation

Tags:

python

django

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

like image 975
Alqueraf Avatar asked Apr 13 '14 17:04

Alqueraf


2 Answers

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.

like image 91
knbk Avatar answered Oct 09 '22 17:10

knbk


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()
like image 41
Daniel Roseman Avatar answered Oct 09 '22 17:10

Daniel Roseman