Search code examples
pythondjangodjango-viewsdjango-queryset

Retrieve object associated in field based on logged in user Django


I have only two models:

class Game(models.Model):
    player1 = models.ForeignKey('Player', related_name='player1' #other details)
    player2 = models.ForeignKey('Player', related_name='player2' #other details)
    player3 = models.ForeignKey('Player', related_name='player3' #other details)

class Player(models.Model):
    owner = models.ForeignKey(User, #other details)
    art = models.URLField()

VIEW:

Once a user submits a link (custom validation in place) via a form, my view creates a Player object and then creates a Game object (if a Game object doesn't exist or is "full" because all player fields are populated) or it updates the next empty player1, player2, or player3 field by associating the newly created Player instance with it.

That works fine, but I'm stuck on how to query something for the next view/template.

QUESTION:

I want to display a Game object to a User who is logged in based on if they are a Player object associated with either player1, player2, or player3.

I don't want it to display just a recent Game object -- say using something like Game.objects.latest() -- because that might not be the one the User is associated with if other Game objects were created.

I cannot figure out how get the correct Game object. Best I can do is get the Player object associated with the User like is in a view:

def upload(request):
    mine = Player.objects.get(owner=request.user)
    
    context = {
         'mine': mine,
          }

But I want to get the Game object so I can display the other two players in the Game (or show a message like "waiting for players").

How?? Feels like it should be easy, but I've been stuck on this for a couple of days.


Solution

  • I want to display a Game object to a User who is logged in based on if they are a Player object associated with either player1, player2, or player3.

    There can be zero, one, or multiple. Even if we would for example retain us to only Games with the user as first player.

    You can get a QuerySet of such Games with:

    from django.db.models import Q
    
    
    def upload(request):
        mine = Player.objects.get(owner=request.user)
        games = Game.objects.filter(
            Q(player1=mine) | Q(player2=mine) | Q(player3=mine)
        )
        context = {'mine': mine, 'games': games}
        return render(request, 'name-of-some-template.html', context)

    Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


    Note: The related_name=… parameter [Django-doc] is the name of the relation in reverse, so from the Profile model to the Game model in this case. Therefore it (often) makes not much sense to name it the same as the forward relation. You thus might want to consider renaming the player1 relation to games_as_player1.