3👍
add in another loop
player_list = list with Player objects
participant_list = list with Participant objects
for player in player_list:
for participant in participant_list:
if player == participant.player:
print participant.status
break
Not the prettiest solution but simple.
2👍
What you want is the values_list()
method for QuerySet
objects.
player_list = Player.objects.filter(...)
participant_list = Participant.objects.filter(...)
participant_player_id_list = participant_list.values_list('player_id', flat=True)
for player in player_list:
if player.id in participant_player_id_list:
print participant_list.get(player_id=player.id).status
- [Django]-Allow a user to vote only once. Django
- [Django]-Connecting a django-registration signal
- [Django]-How do you use django-datatable-view
- [Django]-Type object has not attribute 'get_or_create'
2👍
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
- [Django]-Delete/Destroy/Update list using Django REST API View
- [Django]-Django model field: Checking "if field is not None" vs. "if field"
- [Django]-Error running manage.py syncdb for first time on Heroku: "You need to specify NAME in your Django settings file"
- [Django]-Django on Aptana Studio 3.0
0👍
Along the same lines as the answers by James and John2x, you could roll three interesting python/django features together to do this in a way that is more explicit and probably much faster. The manager methods values_list and in_bulk can be used to build a dictionary of model objects where each object’s id attribute is mapped to the full object. The third trick is a feature of python dictionaries, which can be passed directly to the built-in function set to produce a set from the dictionary’s keys. Like so:
import operator
# Get a bulk dict of player objects.
pl_objs = Player.objects
bulk_players = pl_objs.in_bulk(pl_obj.values_list("id", flat=True))
# Get a bulk dict mapping player.id to Participant instances.
bulk_participants = dict((operator.attrgetter("player_id"), x)
for x in Participant.objects.all())
# Now find the overlap with a set intersection; print status.
for _id in set(bulk_players) & set(bulk_participants):
print bulk_participants[_id].status
- [Django]-Send login credentials to another server
- [Django]-(Django and PIL) encoder error -2 when writing image file
-1👍
or i think you can also do:
player_list = list with Player objects
participant_list = list with Participant objects
for player, participant in zip(player_list, participant_list):
if player == participant.player:
print participant.status
break
but both player_list
and participant_list
have to have the same length
- [Django]-Functional tests=Integration Tests ?in django
- [Django]-Switch to Django Custom User Model, Groups and Permissions