Django: select_related и GenericRelation

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')

Я выбираю набор Требований, и я хотел бы, чтобы связанные Доказательства были втянуты вместо запрошенного индивидуально.

8
задан Parand 30 May 2010 в 17:10
поделиться

2 ответа

Похоже, что select_related и GRs не работают вместе. Я думаю, вы можете написать какой-то аксессор для Claim, который получает их все через один и тот же запрос. В этом посте даны некоторые указания на необработанный SQL для получения общих объектов, если они вам нужны

.
3
ответ дан 5 December 2019 в 07:10
поделиться

Встроенного способа сделать это не существует. Но я опубликовал технику для имитации 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() для общих отношений.

17
ответ дан 5 December 2019 в 07:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: