在Django 2中在注释中使用属性字段

时间:2018-10-31 06:45:28

标签: django django-signals django-2.0

我正在使用Django 2.xDjango REST Framework

我有一个模型 AmountGiven ,其属性字段为 amount_due ,例如

class AmountGiven(models.Model):
    contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
    amount = models.FloatField(help_text='Amount given to the contact')
    interest_rate = models.FloatField(blank=True, default=None, null=True, help_text='% of interest to be calculated')
    total_due = models.FloatField(
        blank=True,
        default=0.0,
        editable=False
    )

    @property
    def interest_to_pay(self):
        if self.interest_rate:
            datetime_diff = datetime.now(get_localzone()) - datetime.combine(
                self.given_date, datetime.min.time(), get_localzone()
            )
            days = datetime_diff.days
            duration_in_year = days/365

            simple_interest_amount = (self.amount * duration_in_year * self.interest_rate)/100

            return simple_interest_amount

        return 0

    @property
    def total_payable(self):
        return self.amount + self.interest_to_pay

    @property
    def amount_due(self):
        returned_amount = 0

        for returned in self.amountreturned_set.all():
            returned_amount += returned.amount

        total_due = self.total_payable - returned_amount

        self.total_due = total_due
        self.save()

        return total_due

我需要为Django REST Framework响应生成图形数据,以获取联系人的应付款总额。

def top_ten_due(request):
    qs = Contact.objects.filter(
        user=request.user
    ).values('first_name', 'last_name').annotate(
        total_due=Sum('amountgiven__total_due')
    ).order_by(
        '-total_due'
    )[:10]

    graph_data = []
    for q in qs:
        d = {
            'contact': q['first_name'] if q['first_name'] else '' + ' ' + q['last_name'] if q['last_name'] else '',
            'value': q['total_due'] if q['total_due'] else 0
        }
        graph_data.append(d)

    return Response(sorted(graph_data, key=lambda i: i['value'], reverse=True))

到期金额由 AmountGiven 模型的 amount_due 属性计算。并且为了生成图形数据,我需要注释到期金额。由于无法注释属性字段,因此我有一个只读字段 total_due ,该字段在每次调用 amount_due 属性时都会更新。然后用于注释。

因此,每次我调用 AmountGiven 对象时,都会更新模型,并因此触发 post_save 信号。

现在,有一个 post_save 信号接收器,用于在每次更新金额时创建日志。

@receiver(post_save, sender=AmountGiven, dispatch_uid='amountgiven12345')
def amount_given_post_save_receiver(sender, instance, created, **kwargs):
    if created:
        action = 'given'
    else:
        action = 'updated'

    log = TransactionLog.objects.filter(
        user=instance.contact.user,
        contact=instance.contact,
        amount_given=instance
    ).order_by('-created').first()

    if not log or log.amount != instance.amount:
        TransactionLog.objects.create(
            user=instance.contact.user,
            contact=instance.contact,
            amount_given=instance,
            amount=instance.amount,
            action=action
        )

尽管我已经使用检查来检查日志是否还不存在或者日志量与实例量是否不同。每次获取 AmountGiven 的列表时,它都会为每个请求触发 post_save ,从而触发接收者并创建日志。

因此,它会在很短的时间间隔内创建大量日志。

如何处理此类问题?

我是否可以在批注中使用 amount_due 属性字段,以使 total_due 不会在每次阻止调用 post_save 时更新?

0 个答案:

没有答案