【问题标题】:Django - prefetch_related GenericForeignKey results and sort themDjango - prefetch_related GenericForeignKey 结果并对它们进行排序
【发布时间】:2020-07-12 07:30:18
【问题描述】:

我有以下结构,其中从通用模型子类化的内容模块通过“页面模块”模型附加到页面,该模型通过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’不生成自动反向关系 因此不能用于反向查询”

...我不认为我可以将推荐的 GenericRelation 字段添加到所有内容模型中,因为那里已经有内容了。

那么……我可以这样做吗?还是我被卡住了?

【问题讨论】:

  • 检查我的问题并回答here我不确定这是否能解决您的订购问题,但至少您可以最大限度地减少所需的查询数量。
  • 嗨 - 谢谢,这很有用。我跟着它到了this article,这是我基于它的解决方案;它使 SQL 查询的数量减半。不幸的是,由于它们现在已被 WHERE IN() 取代,因此这些查询的效率并不是特别高,但至少是一种改进。

标签: django django-models


【解决方案1】:

按照上面 cmets 中的建议,我最终得到了这段代码(从 2012 年开始!),它大致将查询数量减少了一半: https://gist.github.com/justinfx/3095246

但是,正如我上面提到的,这样做是以创建一些相当低效的WHERE pk IN() 查询为代价的,所以我实际上并没有节省太多时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-07
    • 2011-09-21
    • 2013-04-28
    • 1970-01-01
    • 2020-08-09
    • 2022-10-04
    相关资源
    最近更新 更多