Do Django backward relations add computational overhead?
Question:
In Django, you create models and can optionally specify a foreign key on a field
class Man:
...
class Dog:
...
owner = models.ForeignKey(Man, on_delete=models.SET_NULL)
You can then query each Dog
for its respective owner or get all dogs for a Man
owner = some_dog.owner
all_dogs = some_man.dog_set.all()
If you want to not create a backward relation as specified by the docs, you can do
class Man:
...
class Dog:
...
owner = models.ForeignKey(Man, on_delete=models.SET_NULL, related_name='+')
Now you no longer have access to all_dogs = some_man.dog_set.all()
.
However, does this additional "building" of a backward relation add overhead? If I just never ever used all_dogs = some_man.dog_set.all()
would it matter whether or not I had specified related_name='+'
in Dog
? Would it slow things down potentially?
And is this functionality purely implemented in application side Django, or would related_name='+'
also change the database schema itself? Thank you, any insight would be greatly appreciated.
Answers:
However, does this additional “building” of a backward relation add overhead?
No
If I just never ever used all_dogs = some_man.dog_set.all() would it matter whether or not I had specified related_name=’+’ in Dog? Would it slow things down potentially?
No, and no.
And is this functionality purely implemented in application side Django, or would related_name=’+’ also change the database schema itself?
It’s implemented with Python descriptors. In the case of ForeignKey
, that’s a ReverseManyToOneDescriptor
.
There is no change in the database schema, and the presence or absence of a related name does not generate a migration.
If you haven’t disabled the relation, you should actually see the descriptor objects there as attributes on the model classes. Something like this:
>>> Dog.owner
<django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor at 0x105db25d0>
>>> Man.dog_set
<django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor at 0x105db27d0>
These are the objects which make Django’s ORM magic work.
In Django, you create models and can optionally specify a foreign key on a field
class Man:
...
class Dog:
...
owner = models.ForeignKey(Man, on_delete=models.SET_NULL)
You can then query each Dog
for its respective owner or get all dogs for a Man
owner = some_dog.owner
all_dogs = some_man.dog_set.all()
If you want to not create a backward relation as specified by the docs, you can do
class Man:
...
class Dog:
...
owner = models.ForeignKey(Man, on_delete=models.SET_NULL, related_name='+')
Now you no longer have access to all_dogs = some_man.dog_set.all()
.
However, does this additional "building" of a backward relation add overhead? If I just never ever used all_dogs = some_man.dog_set.all()
would it matter whether or not I had specified related_name='+'
in Dog
? Would it slow things down potentially?
And is this functionality purely implemented in application side Django, or would related_name='+'
also change the database schema itself? Thank you, any insight would be greatly appreciated.
However, does this additional “building” of a backward relation add overhead?
No
If I just never ever used all_dogs = some_man.dog_set.all() would it matter whether or not I had specified related_name=’+’ in Dog? Would it slow things down potentially?
No, and no.
And is this functionality purely implemented in application side Django, or would related_name=’+’ also change the database schema itself?
It’s implemented with Python descriptors. In the case of ForeignKey
, that’s a ReverseManyToOneDescriptor
.
There is no change in the database schema, and the presence or absence of a related name does not generate a migration.
If you haven’t disabled the relation, you should actually see the descriptor objects there as attributes on the model classes. Something like this:
>>> Dog.owner
<django.db.models.fields.related_descriptors.ForwardManyToOneDescriptor at 0x105db25d0>
>>> Man.dog_set
<django.db.models.fields.related_descriptors.ReverseManyToOneDescriptor at 0x105db27d0>
These are the objects which make Django’s ORM magic work.