select_related() and ForeignKey(null=True)
Есть такая штука в django - selecte_related. Если вы присовокупите её к какому-нить QuerySet, то она сделает вот что: начнёт сказать по полям ForeignKey объектов из QuerySet и подгружать объекты, если у тех есть ForeignKey, то у них тоже подгрузит что-нибудь и т.д. Глубину проникновения можно регулировать параметром depth. Но есть у этой штуки один недостаток: она не работает с ForeignKey, которые могут быть null.
Я решил написать код, который бы подгружал все объекты по ForeignKey, независимо от того могут они быть null или нет. Сосбственно, вот код :-) Делает он вот что, получает список объектов на входе. Определяет все ForeignKey поля модели, к которой принадлежат объекты. Далее для каждого ForeignKey c помощью дополнительного запроса выцепляет все объекты, которые упомянутые в списке объектов.
О других полезных штуках для подгрузки related объектов, можете почитать у пираньи [piranha.org.ua]
Я решил написать код, который бы подгружал все объекты по ForeignKey, независимо от того могут они быть null или нет. Сосбственно, вот код :-) Делает он вот что, получает список объектов на входе. Определяет все ForeignKey поля модели, к которой принадлежат объекты. Далее для каждого ForeignKey c помощью дополнительного запроса выцепляет все объекты, которые упомянутые в списке объектов.
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 becouse if we set key_obj directly to key.name
# then cache will 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
О других полезных штуках для подгрузки related объектов, можете почитать у пираньи [piranha.org.ua]






Comments
Most people truly employ their information to the very best probable tier. Many people really make use of their knowledge to the most beneficial achievable level.org bot browser bulk replace byteflow cache captcha chromium commands conference css curl dd debian debug debugging decorator design djaba django djangodash. Most people in fact make use of their information to the best achievable tier.org excel exception export fastcgi favicon feedzilla filemanager firebug firefox foreignkey forum google grep html import iphone jabber javascript jquery linkexchange linkfeed linkfeed. Most people actually use their information to the very best probable level.ru linux logrotate mainlink memoryleak mercurial middleware mongodb newforms nginx omsk opensource orm oscon pagination partitions php pip plugin production punbb pybb pycurl pyjob.ru python registration ruby rubyonrails rupy russia sape sape.Right now there ended up being a highly serious issue with this particular topic, plus we all recognize that a new viewpoint is required. Utilizing frequent sense, most people can see the truth now as this is often a heated subject inside the location of printing via the internet. Many people actually utilize their knowledge to the best achievable level.