Django 1.2.1 и load_related_m2m
Программирование 18.07.2010
Интро
Думаю, многие из нас занимались оптимизацие загрузки данных из полей ManyToManyField. Задача для оптимизации проста: есть коллекция объектов с некоторым полем (полями) М2М. Необходимо выбрать данные для поля М2М одним запросом, т.е. не выполнять для каждого объекта из коллекции отдельный запрос, по загрузке однотипных данных.
Думаю, многие для этого писали собственные функции, я же пользовался load_related_m2m, найденной когда-то толи на djbook.ru, толи на сайте Ивана Сагалаева.
И вот при обновлении до Django 1.2.1 при вызове функции load_related_m2m, появилась ошибка: ‘DatabaseWrapper’ object is not callable
Исправляем
Очевидно, произошло это из-за смены интефейсов класса django.db.models.sql.Query. Для возобновления работоспособности необходимо изменить буквально пару строк:
Код
# -*- coding: utf-8 -*-
from django.db.models.sql.constants import LOOKUP_SEP
from django.db.models import sql
from django.db import connection
def load_related_m2m(object_list, field):
select_fields = ['pk']
related_field = object_list.model._meta.get_field(field)
related_model = related_field.rel.to
cache_name = 'all_%s' % field
for f in related_model._meta.local_fields:
select_fields.append('%s%s%s' % (field, LOOKUP_SEP, f.column))
query = sql.Query(object_list.model)
query.add_fields(select_fields)
query.add_filter(('pk__in', [obj.pk for obj in object_list]))
related_dict = {}
cursor = connection.cursor()
cursor.execute(str(query))
for row in cursor.fetchall():
if row[2]:
related_dict.setdefault(row[0], []).append(related_model(*row[1:]))
for obj in object_list:
try:
setattr(obj, cache_name, related_dict[obj.pk])
except KeyError:
setattr(obj, cache_name, [])
return object_list
З.Ы.
А лето выдалось жаркое. Такое чувство, что в тени +40 )








Мою функцию допили :)
Можно ваш вариант добавить на djbook.ru?
Дмитрий, добрый день!
Т.е. начальный вариант этой функции появился на djbook и вы автор? Это что бы мне в тексте статьи поправить авторство )
Конечно, можно! Мне будет приятно знать, что мой patch пригодился кому-то еще )
Эту тему на форуме я и создал :) Попрошу что бы на djbook.ru добавили, но это будет когда у хозяина djbook время найдеться. Еще писал подгрузку связей через GenericForeignKey и ForeignKey с null=True.
Не помню такого ) Поделитесь ссылочкой? )
Изволил написать статью :)
Вот линк.
На djbook добавили линк на вашу статью.
Да толку, все равно не работает, хоть и ошибок не выдает ((
Если выводили в шаблоне, попробуйте во вьюхе. Шаблон “глотает” часть ошибок.
Пардон, работает - забыл сменить .field.all() на .all_field
Спасибо большое. Еще бы обратную функцию для .field_set - было бы вообще здорово :)
ИМХО, методам типа “field_set” все же не место в шаблонах, лучше оставить их контроллерам.
Чем “тупее” шаблон, тем лучше. Тем легче делать редизайны и переносить код от проекта к проекту.
А вто вообще про шаблон говорит? Мне .field_set нужен в вьюхе.
Тогда немного не понимаю Вашу проблему… что именно не получается? Пример в студию!
К примеру, есть модель:
Собственно, как найти всех родителей категории понятно:
А вот бы еще так детей заранее загрузить (здесь Foo.foo_set.all() ) одим запросом.