Как получить счетчик на основе подзапроса? - PullRequest
0 голосов
/ 08 мая 2020

Мне не удается заставить запрос работать, несмотря на все попытки, основанные на моем веб-поиске, и я думаю, что мне нужна помощь, прежде чем сойти с ума.

У меня четыре модели:

class Series(models.Model):
    puzzles = models.ManyToManyField(Puzzle, through='SeriesElement', related_name='series')
    ...

class Puzzle(models.Model):
    puzzles = models.ManyToManyField(Puzzle, through='SeriesElement', related_name='series')
    ...

class SeriesElement(models.Model):
    puzzle = models.ForeignKey(Puzzle,on_delete=models.CASCADE,verbose_name='Puzzle',)
    series = models.ForeignKey(Series,on_delete=models.CASCADE,verbose_name='Series',)
    puzzle_index = models.PositiveIntegerField(verbose_name='Order',default=0,editable=True,)

class Play(models.Model):
    puzzle = models.ForeignKey(Puzzle, on_delete=models.CASCADE, related_name='plays')
    user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True,null=True, on_delete=models.SET_NULL, related_name='plays')
    series = models.ForeignKey(Series, blank=True, null=True, on_delete=models.SET_NULL, related_name='plays')
    puzzle_completed = models.BooleanField(default=None, blank=False, null=False)
    ...

каждый пользователь может сыграть в любую головоломку несколько раз, каждый раз создавая Play запись. это означает, что для данного набора (user,series,puzzle) у нас может быть несколько Play записей, некоторые с puzzle_completed = True, некоторые с puzzle_completed = False

То, что я пытаюсь (безуспешно) достичь, - это вычислить для каждой серии через аннотацию количество головоломок nb_completed_by_user и nb_not_completed_by_user.

Для nb_completed_by_user у меня есть что-то, что работает почти во всех случаях (у меня есть один сбой в одном из моих тестов что я пока не могу объяснить):

Series.objects.annotate(nb_completed_by_user=Count('puzzles',
filter=Q(puzzles__plays__puzzle_completed=True, 
    puzzles__plays__series_id=F('id'),puzzles__plays__user=user), distinct=True))

Для nb_not_completed_by_user я смог сделать запрос на Puzzle, который дает мне хороший ответ, но я не могу преобразовать его в Subquery выражение, которое работает, не вызывая ошибки, или чтобы получить выражение Count, которое даст мне правильный ответ.

Это работает:

puzzles = Puzzle.objects.filter(~Q(plays__puzzle_completed=True,
 plays__series_id=1, plays__user=user),series=s)

но при попытке перейти к подзапросу, я не могу найти способ использовать следующее выражение, чтобы не выдавать ошибку: ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.

pzl_completed_by_user = Puzzle.objects.filter(plays__series_id=OuterRef('id')).exclude(
    plays__puzzle_completed=True,plays__series_id=OuterRef('id'), plays__user=user)

и следующее выражение Count не дает мне правильного результата:

Series.objects.annotate(nb_not_completed_by_user=Count('puzzles', filter=~Q(
            puzzle__plays__puzzle_completed=True, puzzle__plays__series_id=F('id'), 
            puzzle__plays__user=user))

Кто-нибудь может объяснить мне, как я мог получить оба значения ? и, в конце концов, предложить мне ссылку, которая четко объясняет, как использовать подзапросы для менее очевидных случаев, чем те, которые указаны в официальной документации

Заранее спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...