Мне не удается заставить запрос работать, несмотря на все попытки, основанные на моем веб-поиске, и я думаю, что мне нужна помощь, прежде чем сойти с ума.
У меня четыре модели:
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))
Кто-нибудь может объяснить мне, как я мог получить оба значения ? и, в конце концов, предложить мне ссылку, которая четко объясняет, как использовать подзапросы для менее очевидных случаев, чем те, которые указаны в официальной документации
Заранее спасибо