Django’s ORM (version 1.2.3) does not preserve identity when following foreign keys back and forth. This is best explained with an example:
class Parent(models.Model):
pass
class Child(models.Model):
parent = models.ForeignKey(Parent)
parent = Parents.objects.get(id=1)
for child in parent.child_set.all():
print id(child.parent), "=!", id(parent)
So, for each child the parent is re-fetched from the database, even though we know the parent at the moment we fetch the child. This is counterintuitive to me.
In my case this also leads to performance issues, since I do some heavy operations at the parent level which I’d like to cache at object instance level. However, since the results of these calculations are accessed via the child => parent link, this caching at the parent level is useless.
Any ideas on how to solve this?
I’ve gotten as far as figuring out there’s a ForeignRelatedObjectsDescriptor and a ReverseSingleRelatedObjectDescriptor.
There are a number of possible solutions to this.
Perhaps the easiest is to keep track of the parent yourself:
_FOO_cacheis the way Django keeps track of items fetched via ForeignKey, so if you pre-populate that object on the child with the parent you already have, Django won’t fetch it again when you referencechild.parent.Alternatively, you could look into one of the third-party libraries that attempt to fix this – django-idmapper or django-selectreverse are two I know of.