Django select_related in reverse

瘦欲@ 提交于 2021-02-06 10:49:21

问题


I have the following model:

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

In other words, I have Campaigns which can have multiple Positions. In turn each position within the campaign can have multiple Trades.

Is there an efficient way (ie: minimal database calls) to select a Campaign along with all of its associated Positions and Trades. It doesn't look like I can use select_related because that only works the other way, eg: for a specific Trade, select_related will get all of the associated Positions.

Currently I am doing this in nested loops as follows:

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

This works correctly but is very inefficient in terms of how many times the database gets hit. I there a better way to do this? Something along the lines of select_related but in reverse? A way to do one large query to get all Campaigns along with the associated Positions and Trades without having to loop through each individually.


回答1:


Thanks to the suggestions in the comments, I ended up with the following working solution:

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

Edit: it should be added this import

from django.db.models import Prefetch

Ref. Prefetch docs



来源:https://stackoverflow.com/questions/37652520/django-select-related-in-reverse

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!