Запросы к базе данных Django

Я хочу изменить этот код для более быстрого запроса

response = []

for player in Player.objects.all():
   total_earn = Credit.objects.filter(player=player).aggregate(Sum('amount')).get('amount__sum', 0)
   total_earn += Purchase.objects.filter(player=player).aggregate(Sum('amount')).get('amount__sum', 0)
   reponse.append([player.id, player.email, player.phone, total_earn])

Я попробовал это на мгновение, но теперь для выполнения требуется много времени, и это вызывает тайм-аут на сервере.

Я хочу что-то очень быстрое, типа этого:

response = Player.objects.annotate(
  id='id',
  email='email',
  phone='phone',
  total_earn=(Credit.... + Purchase....)
)

Мои модели:

class Player(AbstractUser):
   email = models.EmailField(..)
   phone = models.CharField(..)

class Credit(models.Model):
   player = models.ForeignKey(Player, ..., CASCADE)
   amount = modesl.DecimalField(decimal_places=2, ...)

class Purchase(models.Model):
   player = models.ForeignKey(Player, ...)
   amount = models.DecimalField(decimal_places=2, ...)

Вы можете использовать подзапросы:

from django.db.models import OuterRef, Subquery

credits = Credit.objects.filter(
    player=OuterRef('pk')
).values('player').annotate(
    total=Sum('amount')
).order_by('player').values('total')

purchases = Purchases.objects.filter(
    player=OuterRef('pk')
).values('player').annotate(
    total=Sum('amount')
).order_by('player').values('total')

Player.objects.annotate(
    total_earn=Subquery(credits)[:1] - Subquery(purchases)[:1]
)

Как бы то ни было, похоже, что здесь имеет место плохое моделирование. Возможно, было бы лучше сделать одну модель для Credits и Purchases и, таким образом, использовать отрицательную сумму для Purchases. Если такая модель называется, например, Earning, то это можно сделать с помощью простого Player.objects.annotate(total_earn=Sum('earning__amount')).

Вернуться на верх