Вычислить сумму из другой таблицы в Django - PullRequest
0 голосов
/ 03 марта 2020

Мне нужно создать модель в Django для следующего:

Invoice table -> invoice_id, order_id, unit_price, num_units
                  1, 1, 10, 5
                  1, 2, 10, 5
                  2, 1, 10, 5
                  2, 2, 10, 5
                  3, 3, 10, 5
                  3, 1, 10, 5
                  3, 2, 10, 5

Invoice Summary table -> invoice_id, sum
                          1, 100
                          2, 100
                          3, 150 

Как должна выглядеть моя модель для приведенных выше таблиц в Django?

Я пытался:

class Invoice(models.Model):
      inv_id = models.IntegerField()
      order_id = models.IntegerField()
      unit_price = models.IntegerField()
      num_units = models.IntegerField()

class Summary(models.Model):
      invoice_id = 
      sum = invoice_id total sum i.e ( unit_price * num_units ) for invoice_id

Как моя сводная модель будет выглядеть так, что я получу правильный результат для определенного идентификатора счета-фактуры?

Ответы [ 3 ]

1 голос
/ 03 марта 2020

Вы можете использовать Foreignkey для соединения сводной модели с моделью Invoice. Если вы не импортируете свой идентификатор счета-фактуры, вам не нужно использовать inv_id, поскольку django автоматически генерирует поле идентификатора.

class Summary(models.Model):
    invoice = models.Foreignkey(Invoice,on_delete=models.CASCADE) #Cascade means if your invoice is deleted, related summaries deleted, too.
    sum = models.IntegerField()

Вы можете использовать сигналов для расчета суммы поля. Но не забывайте, что при обновлении не генерируются сигналы. В основном, вы можете создать храмовое поле в результате, которое содержит умножение num_units и unit_price, после того, как вы суммируете с помощью метода aggreagate это храмовое поле. Вы можете использовать текущее значение поля с F выражением.

в ваших signal.py:

def calculate_sum_of_invoice(sender, **kwargs):
    invoice_id = kwargs.get('instance').id
    summary = Invoice.objects.filter(id=invoice_id).annotate(
result=F('unit_price') * F('num_units')).aggregate(Sum('result'))['result__sum'])
    Summary.objects.update_or_create(
    invoice_id=invoice_id, defaults={"sum": summary}


post_save.connect(calculate_sum_of_invoice, sender=Invoice, dispatch_uid="invoice-save-signal")
0 голосов
/ 03 марта 2020

Если вы хотите сохранить sum в таблице Summary, вам не нужно создавать отдельную таблицу, вы можете просто добавить поле sum в Invoice таблица, а затем вы можете использовать Сигнал для расчета и хранения суммы.

Однако здесь предлагается предлагаемое решение, если вы хотите его таким образом:

class Summary(models.Model):
    invoice = models.OneToOneField(
        Invoice,
        on_delete=models.CASCADE,
        primary_key=True,
    )

    sum = models.IntegerField(default=0)

с использованием Сигнал сохранения после записи

from django.db.models.signals import post_save
from django.db.models import Sum


def update_invoice_summary(sender, instance, **kwargs)
    try:
        obj = Summary.objects.get_or_create(invoice=instance)
        obj.sum += instance.unit_price * instance.nums_unit
    except Summary.DoesNotExist:
        obj = Summary(instance, instance.unit_price * instance.nums_unit)

    obj.save()


post_save.connect(update_invoice_summary, sender=Invoice)
0 голосов
/ 03 марта 2020
from django.db.models import Sum

sum = Invoice.objects.all().values('unit_price').annotate(
    average_grade=Sum('unit_price') * F('num_units'))

изменить модель.py

class Summary(models.Model):
    invoice = models.Foreignkey(Invoice,on_delete=models.CASCADE)
    sum = models.IntegerField()
...