Django utility for loading related objects by foreign key (works even foreign key could be null)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def load_foreign(object_list, foreign_keys=None):
"""
Load foreign key objects which could be null
"""
if not object_list:
return object_list
object = object_list[0]
from django.db.models.fields.related import ForeignKey
if foreign_keys is None:
foreign_keys = []
for field in object._meta.fields:
if isinstance(field, ForeignKey):
foreign_keys.append(field.name)
for x in xrange(len(foreign_keys)):
key = object._meta.get_field(foreign_keys[x])
foreign_keys[x] = key
fk_ids = [getattr(x, '%s_id' % key.name) for x in object_list]
fk_ids = filter(None, fk_ids)
key.cache = dict([(x.pk, x) for x in key.rel.to.objects.filter(pk__in=fk_ids)])
for obj in object_list:
for key in foreign_keys:
key_obj = key.cache.get(getattr(obj, '%s_id' % key.name), None)
# Use cache_name because if we set key_obj directly to key.name
# then cache will be erased and in next call to foreign key related object will
# be loaded from DB
# see django.db.models.fields.related.ReverseSingleRelatedObjectDescriptor for details
setattr(obj, key.get_cache_name(), key_obj)
return object_list