Prefetch on a one-to-many in Django not behaving as expected
Asked Answered
T

1

0

I have a simple one-to-many relationship in Django, for example:

class Team(models.Model):

    team_mascot = models.CharField(
        max_length=200, null=True)

class Player(models.Model):

    first_name = models.CharField(max_length=200, null=True)
    last_name = models.CharField(max_length=200, null=True)

    team = models.ForeignKey(
        'players.Team',
        blank=True, null=True,
        on_delete=models.SET_NULL,
        related_name='players',
        related_query_name='player',
    )

On the Player admin page(s), I want to display some information about the Team associated with that player if the player has a team, including information about other players on that team. I want to optimize this query with a prefetch for all the related players to the current players' team. This should be fairly simple, but I can't seem to get the right prefetch.

Here's what I've tried:

def prefetch_all_team_players(self):

  return self.prefetch_related(
    Prefetch('team__players', to_attr='all_team_players')
    )

and:

def prefetch_all_team_players(self):
    return self.select_related('team').prefetch_related(
        Prefetch(
            'team__players',
            to_attr='all_team_players'
        )
    )

and:

def prefetch_all_team_players(self):
    from myproj.players.models import Team

    team_queryset = Team.objects.all()
    return self.prefetch_related(
        Prefetch('team__players', to_attr='all_team_players', queryset=team_queryset)
        )

I'm using this on the appropriate admin page. However, all_team_players is not being populated as expected. I'm not getting any value. player.all_team_players.all() doesn't give me anything.

The alternative is of course just using player.team.players.all() wherever I need it, which works. But I'm trying to gain performance with the prefetch.

Any ideas on what I'm missing here?

Tomasz answered 28/11, 2017 at 16:53 Comment(0)
T
1

I figured it out - pretty simple. The first and second prefetch statements are just fine. However the way I was accessing them was not. Should have accessed like so:

player.team.all_team_players

forgot to access the team first thru player, then the attribute is accessible. Doh

Tomasz answered 29/11, 2017 at 3:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.