Джанго создать подтаблицу - PullRequest
0 голосов
/ 15 мая 2018

У меня есть три модели, как показано ниже:

class Person(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)

class PersonSession(models.Model):
    start_time = models.DateTimeField(auto_now_add=True)
    end_time = models.DateTimeField(null=True,
                                    blank=True)
    person = models.ForeignKey(Person, related_name='sessions')

class GameSession(models.Model):
    score = models.PositiveIntegerFeild()
    person_session = models.ForeignKey(PersonSession, related_name='games')

Теперь я хочу получить список людей с подсчитанными всеми оценками, которые они получают, плюс время, которое они проводят во всех своих игровых сессиях и сеансах веток, в настоящее время я использую следующий запрос:

Person.objects.annotate(game_score=Sum(Case(When(Q(sessions__games__isnull=True),
                                       then=0),
                                  default=F('sessions__games__score'),
                                  output=models.PositiveIntegerField())))\
    .annotate(spent_time=Sum(Case(When(Q(branch_sessions__isnull=False) &
                                       Q(branch_sessions__end_time__isnull=False),
                                       then=ExpressionWrapper(ExtractHour(ExpressionWrapper(F('sessions__end_time')-F('sessions__start_time'),
                                                                                            output_field=models.TimeField()),
                                                                          output=models.PositiveIntegerField()) * 60 + \
                                                              ExtractMinute(ExpressionWrapper(F('sessions__end_time')-F('sessions__start_time'),
                                                                                              output_field=models.TimeField()),
                                                                            output=models.PositiveIntegerField()),
                                                              output_field=models.PositiveIntegerField())),
                                  default=0,
                                  output=models.PositiveIntegerField()))) \
    .annotate(total_score=F('game_score') + F('spent_time') * SCORE_MIN)\
    .order_by('-total_score')

Проблема в том, что этот запрос объединяет все таблицы вместе, поэтому для каждого PersonSession может быть много GameSession, а в результирующей таблице содержится повторяющаяся строка сеанса с пользователем, которая приводит к тому, что время сеансов с индивидуальными суммами повторяется и генерирует неправильный результат.

В SQL-запросе я должен сначала создать подтаблицу с суммой игровых значений, а затем соединить эту таблицу с сеансом персонажей, но я не знаю, как это возможно в django?

Я использую django 1.11 и postgres.

...