AMG
AMG

Reputation: 1646

Chaining queries through related objects

Given a scenario like:

from django.db import models

class Player(models.Model):
    playername = models.CharField()

class Team(models):
    teamname = models.CharField()

class Members(models):
    player = models.ForeignKey(Player)
    team = models.ForeignKey(Team)

class Division(models):
    divname = models.CharField()  

class DivisionTeam(models):
    division = models.ForeignKey(Division)
    team = models.ForeignKey(Team)

How can I list all distinct players in division id = 5? I've look through the Q and F expressions, but I'm not looking for a complex set of or's. I am wondering if there is a way to chain a number of object1_set.object2_set.all() type structures, or do I set up a nested loops to build the object (to be passed to template via context) with eventual {% for p in players %} type loop in the template. The div id is passed through as a request variable.

Upvotes: 2

Views: 281

Answers (2)

YPCrumble
YPCrumble

Reputation: 28682

You would do best to simplify your models first. I don't think you need either of the Members or DivisionTeam models:

from django.db import models

class Division(models):
    divname = models.CharField()

class Team(models):
    teamname = models.CharField()
    division = models.ForeignKey(Division)

class Player(models.Model):
    playername = models.CharField()
    team = models.ManyToManyField(Team)

Then, your query is simply:

Player.objects.filter(team__division__pk=5)

In case you DO need intermediate models per comments, you should use a through relationship:

# Uses "Salary" as an example intermediate model.
class Player(models.Model):
    playername = models.CharField()
    team = models.ManyToManyField(Team, through="Salary")

class Salary(models.Model):
    value = models.IntegerField()
    player = models.ForeignKey(Player)
    team = models.ForeignKey(Team)

Upvotes: 1

karthikr
karthikr

Reputation: 99620

You could do:

players = Player.objects.filter(members__team__divisionteam__division_id=5).distinct()

Of course, as suggested in the other answer, your models could be simplified (by using ManyToMany rather than explicitly managing it)

Upvotes: 1

Related Questions