For smaller sets of players/participants, a lookup dict is enough:
player_list = Player.objects.all()
# Get all relevant participants (or just all if you like)
player_ids = player_list.value_list('id', flat=True)
participant_list = Participant.objects.filter(player_id__in=player_ids)
# Create a lookup dict
participants = dict([(p.player_id, p) for p in participant_list])
# Everything is now prepared for quick access
for player in player_list:
if player.id in participants:
print participants[player.id].status
If you have to do this often, you might want to use a different approach. Here are three alternatives.
Inheritance
Use inheritance and to store the status in the database. This would make similar queries in the future much easier/more efficient:
class Player(models.Model):
name = models.CharField(max_length=128)
is_participant = models.BooleanField(default=False)
class Participant(Player):
status = models.CharField(max_length=32)
def save(self, *args, **kwargs):
if not self.id:
self.is_participant = True
super(Participant, self).save(*args, **kwargs)
Having your data structured like this means that Participant objects always have the same fields as Player objects and that you can check if a player is a participant without hitting the database or looping through all the participants. Fetching the relevant participant however will incur a hit. A variation on this approach would be to attach a generic foreign key to the Player. Checking the attribute for None will tell you if the player is a participant too, and following the link will take you to the relevant database object.
Denormalisation
If status is the only value you need, you can store it on the player model too, and automatically synchronise it with your Participant value. if you use inheritance as above, you'll get it for free:
class Player(models.Model):
name = models.CharField(max_length=128)
participant_status = models.CharField(max_length=32)
class Participant(Player):
pass
You can query it like this:
for player in Player.objects.all()
if player.participant_status:
print participant.status
One drawback is that you will have to hide the status field from player forms. But the benefit is that you will be able to query a) if the player is a participant and b) get the status without hitting the database.
But this design is certainly not as clean as a normalised database, and it should only really be done if the cost is too great.
One to one relation
A final approach is to use the OneToOneField if this is a one to one relation. Theoretically you can link the two models from either side, but I'm not sure how this works with select_related(), which is what you'll want to use to avoid hitting the database more than once on lists.
class Player(models.Model):
name = models.CharField(max_length=128)
participant = models.OneToOneField('Participant', null=True)
class Participant(models.Model):
status = models.CharField(max_length=32)
You query it like this:
player_list = Player.objects.all().select_related('participant')
for player in player_list:
if player.participant_id is not None:
print player.participant.status