Проблемы с суммированием и вычитанием в Django и PostgreSQL
У меня проблема с квери (получение суммы элемента (агрегата) и вычитание.
).Что я пытаюсь сделать: 10 (soldfor) - 2 (paid) - 2 (shipcost) = 6
Проблема в том, что если я добавлю еще один (soldfor) (paid) или (shipcost) = он сложит их все, так что прибыль станет двойной. Другой пример, если у меня есть товар с (paid), указанным в 3.56 и другой товар с тем же (paid) int, он вычитает эти два из каждой новой строки. Я попробовал два запроса и не могу заставить их работать.
Что я получаю: 10 (soldfor) - 2 (paid) - 2 (shipcost) = 12, потому что два поля имеют одинаковый точный ввод.
По сути, если два поля имеют одинаковый номер, он добавляет или вычитает их к каждой строке, которая имеет такое же поле с таким же номером.
models.py
class Inventory(models.Model):
product = models.CharField(max_length=50)
description = models.CharField(max_length=250)
paid = models.DecimalField(null=True, max_digits=5, decimal_places=2)
bin = models.CharField(max_length=4)
listdate = models.DateField(null=True, blank=True)
listprice = models.DecimalField(null=True, max_digits=5, decimal_places=2, blank=True)
solddate = models.DateField(null=True, blank=True)
soldprice = models.DecimalField(null=True, max_digits=5, decimal_places=2, blank=True)
shipdate = models.DateField(null=True, blank=True)
shipcost = models.DecimalField(null=True, max_digits=5, decimal_places=2, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateField(auto_now=True)
def __str__(self):
return self.product + "\n" + self.description + "\n" + self.paid + self.bin + "\n" + self.listdate + "\n" + self.listprice + "\n" + self.solddate + "\n" + self.soldprice + "\n" + self.shipdate + "\n" + self.shipcost
@property
def Calculate_profit(self):
soldfor = Inventory.objects.filter(soldprice=self.soldprice).aggregate(Sum('soldprice'))['soldprice__sum'] or 0.00
paidfor = Inventory.objects.filter(paid=self.paid).aggregate(Sum('paid'))['paid__sum'] or 0.00
shipfor = Inventory.objects.filter(shipcost=self.shipcost).aggregate(Sum('shipcost'))['shipcost__sum'] or 0.00
totalprofit = soldfor - paidfor - shipfor
return totalprofit
и views.py
@login_required(login_url="/login")
def profitsperitem(request):
inventory = Inventory.objects.filter(soldprice__isnull = False, shipcost__isnull = False).order_by('id')
return render(request, 'portal/profitsperitem.html', {"inventory": inventory})
Я также пробовал просто выполнить этот запрос в views.py
totals = Inventory.objects.aggregate(
Sum('paid'),
Sum('soldprice'),
Sum('shipcost')
)
totalprofit = totals['soldprice__sum'] - totals['paid__sum'] - totals['shipcost__sum']
return render(request, 'portal/profitsperitem.html', {"inventory": inventory, "totalprofit": totalprofit})
Как сделать так, чтобы это было только для данного товара, а не для других товаров, которые могут иметь такие же поля (soldfor) (paid) или (shipcost)?
Учитывая, что я понимаю, что вы пытаетесь сделать, вы можете просто работать с:
class Inventory(models.Model):
# …
def __str__(self):
return f'{self.product}\n{self.description}\n{self.paid}{self.bin}\n{self.listdate}\n{self.listprice}\n{self.solddate}\n{self.soldprice}\n{self.shipdate}\n{self.shipcost}'
@property
def profit(self):
return self.soldprice - self.paidfor - self.shipcost
Поскольку поля могут быть NULLable (что усложняет задачу), возможно, вам придется работать со значениями по умолчанию:
class Inventory(models.Model):
# …
@property
def profit(self):
return (self.soldprice or 0.00) - (self.paidfor or 0.00) - (self.shipcost or 0.00)
Но использование 0.00
в качестве "запасного значения" немного странно, если это NULL
: NULL
обычно означает "неизвестно", а не ноль. Поэтому в этом случае, если одно из полей равно None
, мы возвращаем None
:
class Inventory(models.Model):
# …
@property
def profit(self):
if self.soldprice is not None and self.paidfor is not None and self.shipcost is not None:
return self.soldprice - self.paidfor - self.shipcost