Django - prefetch_related GenericForeignKey результаты и сортировать их - PullRequest
1 голос
/ 31 марта 2020

У меня есть нижеприведенная структура, где модули контента, которые разделены на подклассы из общей модели, прикрепляются к страницам с помощью модели «модуль страницы», которая ссылается на них через GenericForeignKey:

class SitePage(models.Model):
    title = models.CharField()
    # [etc..]

class PageModule(models.Model):
    page = models.ForeignKey(SitePage, db_index=True, on_delete=models.CASCADE)
    module_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    module_id = models.PositiveIntegerField()
    module_object = GenericForeignKey("module_type", "module_id")

class CommonModule(models.Model):
    published_time = models.DateTimeField()

class SingleImage(CommonModule):
    title = models.CharField()
    # [etc..]

class Article(CommonModule):
    title = models.CharField()
    # [etc..]

На данный момент заполнение страниц из этого приводит к большому количеству SQL запросов. Я хочу извлечь все содержимое модуля (то есть все экземпляры SingleImage и Article) для данной страницы наиболее эффективным способом работы с базой данных.

Я не могу просто сделать прямое prefetch_related, потому что оно "должно быть ограничено однородным набором результатов" , и я выбираю несколько типов контента.

Я могу получить каждый тип модуля индивидуально:

image_modules = PageModule.objects.filter(page=whatever_page, module_type=ContentType.objects.get_for_model(SingleImage)).prefetch_related('module_object_')
article_modules = PageModule.objects.filter(page=whatever_page, module_type=ContentType.objects.get_for_model(Article)).prefetch_related('module_object')

all_modules = image_modules | article_modules

Но я нужно отсортировать их:

all_modules.order_by('module_object__published_time')

и я не могу, потому что:

"Поле 'module_object' не генерирует автоматическое c обратное отношение и поэтому не может использоваться для обратных запросов "

... и я не думаю, что смогу добавить рекомендованное поле GenericRelation ко всем моделям контента, потому что там уже есть контент.

Так ... я могу сделать это вообще? Или я застрял?

1 Ответ

0 голосов
/ 01 апреля 2020

Следуя совету в комментариях выше, я в итоге пришел к этому коду (с 2012 года!), Который примерно вдвое сократил количество запросов: https://gist.github.com/justinfx/3095246

Однако, как я уже отметил выше, это сделано за счет создания довольно неэффективных WHERE pk IN() запросов, поэтому я не сэкономил много времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...