Запросы к базе данных 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')).