Выполнение агрегатной функции на объединении Django queryset с переименованными полями приводит к ошибке django.db.utils.DatabaseError

Я использую Django 3.2

Я пытаюсь создать запрос, который запрашивает две различные модели и делает следующее:

  • переименовывает возвращаемые столбцы (чтобы запросы можно было "объединить" вместе
  • )
  • "объединяет" два набора запросов (после переименования столбцов с помощью annotate)
  • пытается запустить агрегатную функцию Sum на объединении (вот где она глючит).

Это упрощенная версия моей кодовой базы:

Модели

class EventCategory(models.Model):
    name = models.CharField(max_length=16)


class Event(models.Model):
    name = models.CharField(max_length=32)
    category = models.ForeignKey(EventCategory, on_delete=models.CASCADE)


class Tournament(models.Model):
    name = models.CharField(max_length=32)
    category = models.ForeignKey(EventCategory, on_delete=models.CASCADE)
    prize_money = models.IntegerField()



class TournamentAward(models.Model):
    awardee =  models.ForeignKey(setting.AUTH_USER_MODEL, on_delete=models.CASCADE)
    tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)



class Game(models.Model):
    player =  models.ForeignKey(setting.AUTH_USER_MODEL, on_delete=models.CASCADE)
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    payment = models.SmallPositiveInteger()
    created_at = models.DateTimeField(auto_now_add=True)

Запросы

payment_earned_today = Game.objects.filter(
                                          player=user,
                                          created_at__year=year, 
                                          created_at__month=month, 
                                          created_at__day=day
                                            ).annotate(category=models.F('event__category'))\
                                       .only('category','payment')
        
        
  
  tournament_prize_today = TournamentAward.objects.filter(
                                          awardee=user,
                                          created_at__year=year, 
                                          created_at__month=month, 
                                          created_at__day=day
                                      ).select_related('tournament__category')\                                            
                              .annotate(category=models.F('tournament__category'))\                                           
                              .annotate(payment=models.F('tournament__prize_money'))\
                              .only('category','payment')


# Union the two querysets ...
union_queryset = payment_earned_today.union( tournament_prize_today )
results = union_queryset.aggregate(total=models.Sum('payment'))

В строке, когда я пытаюсь вычислить общую сумму, я получаю следующую ошибку:

django.db.utils.DatabaseError: ORDER BY не разрешен в подзапросах составных операторов

Как я могу объединить две модели и вычислить агрегатную функцию на объединении?

сначала:

вам не нужно переименовывать поля.

filter_query = Q(created_at__year=year,created_at__month=month,created_at__day=day)

payment_earned_today = Game.objects.filter(player=user, filter_query).values('event__category'. 'payment')

в секунду:

вы можете установить order_by перед агрегатом.

queryset.query.order_by=None 

на третьем:

Почему вы не идете от category?

event_query = Q(event__game__created_at__year=year, event__game__created_at__month=month, event__game__created_at__day=day, event__game__player=user)

tournament_query = Q(tournament__tournamentaward__created_at__year=year, tournament__tournamentaward__created_at__month=month, tournament__tournamentaward__created_at__day=day, tournament__tournamentaward__awardee=user)

all_category = EventCategory.ojects.filter(event_query | tournament_query)

Я не понимаю, является ли ошибка в вашей последней строке ядра или нет: results является множественным числом, но у вас есть aggregate(sum), это дает вам только один результат. Поэтому:

all_category_with_summ_in_day_for_user = all_category.annotate(Sum('tournament__prize_money'), Sum('event__game__payment'))

# or

summs_for_all_category_in_day_for_user= all_category.aggregate(Sum('tournament__prize_money'), Sum('event__game__payment'))
Вернуться на верх