select_related работает на отношения GenericRelation или является там разумной альтернативой? В данный момент выполнение Django человека sql призывает к каждому объекту в моем queryset, и я хотел бы избежать что с помощью чего-то как select_related.
class Claim(models.Model):
proof = generic.GenericRelation(Proof)
class Proof(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
Я выбираю набор Требований, и я хотел бы, чтобы связанные Доказательства были втянуты вместо запрошенного индивидуально.
Похоже, что select_related и GRs не работают вместе. Я думаю, вы можете написать какой-то аксессор для Claim, который получает их все через один и тот же запрос. В этом посте даны некоторые указания на необработанный SQL для получения общих объектов, если они вам нужны
.Встроенного способа сделать это не существует. Но я опубликовал технику для имитации select_related
на общих отношениях в своем блоге.
Краткое содержание блога:
Мы можем использовать поле _content_object_cache
Django, чтобы по сути создать свой собственный select_related
для общих отношений.
generics = {}
for item in queryset:
generics.setdefault(item.content_type_id, set()).add(item.object_id)
content_types = ContentType.objects.in_bulk(generics.keys())
relations = {}
for ct, fk_list in generics.items():
ct_model = content_types[ct].model_class()
relations[ct] = ct_model.objects.in_bulk(list(fk_list))
for item in queryset:
setattr(item, '_content_object_cache',
relations[item.content_type_id][item.object_id])
Здесь мы получаем все различные типы содержимого, используемые отношениями в наборе запросов, и набор отдельных идентификаторов объектов для каждого из них, затем используем встроенный метод менеджера in_bulk, чтобы получить все типы содержимого сразу в готовый к использованию словарь с ключом по ID. Затем мы выполняем один запрос для каждого типа содержимого, снова используя in_bulk, чтобы получить все фактические объект.
Наконец, мы просто устанавливаем соответствующий объект в каталог поле _content_object_cache исходного элемента. Причина, по которой мы это делаем, заключается в том, что это атрибут, который Django будет проверять и заполнять при необходимости, если вы вызовете x.content. если бы вы вызвали x.content_object напрямую. Предварительно заполняя его, мы гарантируем, что Django никогда не потребуется вызывать отдельный поиск - по сути, мы реализуем своего рода select_related() для общих отношений.