Django select_related 反向

Posted

技术标签:

【中文标题】Django select_related 反向【英文标题】:Django select_related in reverse 【发布时间】:2016-10-05 18:31:00 【问题描述】:

我有以下型号:

class Campaign(models.Model):
    some_campaign_field = models.CharField()

class Position(models.Model):
    campaign = models.ForeignKey(Campaign)
    some_position_field = models.CharField()

class Trade(models.Model):
    position = models.ForeignKey(Position)
    some_trade_field = models.CharField()

换句话说,我有可以有多个职位的广告系列。反过来,活动中的每个职位都可以有多个交易。

是否有一种有效的方法(即:最少的数据库调用)来选择一个活动及其所有相关的头寸和交易。看起来我不能使用select_related,因为这只能以另一种方式工作,例如:对于特定的交易,select_related 将获得所有相关的头寸。

目前我在嵌套循环中这样做:

campaigns = Campaign.objects.get()
for campaign in campaigns:
    positions = campaign.position_set.all()
    for position in positions:
        trades = position.trade_set.all()
        # do stuff

这可以正常工作,但就数据库被命中的次数而言效率很低。我有更好的方法来做到这一点吗?类似于select_related 的东西,但反过来呢?一种进行大型查询以获取所有广告系列以及相关头寸和交易的方法,而无需逐个循环。

【问题讨论】:

prefetch_related 怎么样?它会单独查找并更新 python 中多对一和多对多关系的实例。 prefetch_related 并通过 .values() 和 .values_list() 仅获取需要的字段 太好了,谢谢。我知道 prefetch_related 但并不真正了解它的用途。到现在为止。 【参考方案1】:

感谢 cmets 中的建议,我最终得到了以下可行的解决方案:

open_campaigns = list(Campaign.objects.prefetch_related(
                                       Prefetch('position_set',
                                                queryset=Position.objects.all(),
                                                to_attr='cached_positions'),
                                       Prefetch('cached_positions__trade_set',
                                                to_attr='cached_trades'),
                                       ).filter(exit_datetime__isnull=True))

编辑:此导入也是必需的

from django.db.models import Prefetch

参考。 Prefetch docs

【讨论】:

您是如何设法访问 cached_positions 的? 这可能是关于该主题的唯一问题和答案!很好的解决方案,谢谢。我一直在寻找类似的东西。我有一组类似的关系,我一直在为 WRT 序列化而苦苦挣扎。

以上是关于Django select_related 反向的主要内容,如果未能解决你的问题,请参考以下文章

select_related 与反向外键

django: select_related() 在一个已经存在的对象上?

Django 管理员内联:select_related

如何使用'select_related'从相关(ForeignKey)django模型中接收并非所有字段

Django:select_related() 的用法和执行时间性能

django 2.1 上的 select_related 不工作