Search code examples
python-3.xdjango

queryset objects in which user has an object


App has Game model and Player model.

## PLAYER MODEL
class Player(models.Model):
    owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
    art = models.URLField(max_length=150)

## GAME MODEL

# This is the Game model.
class Game(models.Model):

    this_id = models.AutoField(primary_key=True)

    player1 = models.ForeignKey('Player', on_delete=models.SET_NULL, related_name='player1', null=True, blank=True)
    player2 = models.ForeignKey('Player', on_delete=models.SET_NULL, related_name='player2', null=True, blank=True)
    player3 = models.ForeignKey('Player', on_delete=models.SET_NULL, related_name='player3', null=True, blank=True)

    p1_final_points = models.PositiveIntegerField(default=0)
    p2_final_points = models.PositiveIntegerField(default=0)
    p3_final_points = models.PositiveIntegerField(default=0)

    genre = models.CharField(max_length=7, default='')
    
    ### is the game completed
    completed = models.BooleanField(default=False)


I want to get a list of the Game objects in which the logged in user has a Player. This is to show that user's Game history in a dashboard so they can see past games.

This code gets all the Game objects. So it shows the history of every user.

class DashboardListView(generic.ListView):
    model = Game
    template_name = 'dashboard.html'
    context_object_name = 'tournament_list'

    def get_queryset(self):
        return Game.objects.filter()

I can narrow down to completed games for every player like this:

class DashboardListView(generic.ListView):
    model = Game
    template_name = 'dashboard.html'
    context_object_name = 'tournament_list'

    def get_queryset(self):
        return Game.objects.filter(completed=True)

I tried this to get to narrow down to only games of the specific user:

def get_queryset(self):
        if Player.objects.filter(owner=self.request.user).exists():
            mine = Player.objects.filter(owner=self.request.user).get()
            return Game.objects.filter(
            Q(player1=mine) | Q(player2=mine) | Q(player3=mine) & Q(completed=True))
        

But because there are multiple Player objects for the user it throws this error:

get() returned more than one Player -- it returned 12!

What I want are the 12 Games in which the user has those 12 Player objects.

How can I get those Game objects in which the user has a Player object?


Solution

  • from django.db.models import Q
    
    def get_queryset(self):
      p = Player.objects.filter(owner=self.request.user)
      g = Game.objects.filter(completed=True)\
        .filter(Q(player1__in=p)|Q(player2__in=p)|Q(player3__in=p))
      return g