保存模型时如何在同一模型的字段中添加值-Django管理员

时间:2019-02-05 17:13:45

标签: django django-admin

我有一个看起来像这样的django模型...

class Account(models.Model):
  account_name = models.CharField(max_length=100)
  deposited_amount = models.PositiveIntegerField(default=0)
  opening_balance = models.IntegerField(default=0)
  current_balance = models.CharField(max_length=9)

在我的admin.py文件中,我将current_balance字段设置为只读。我希望当前余额为deposited_amountopening_balance的总和,因此我已经实现了一个信号来尝试处理该问题……

@receiver(post_save, sender=Account, dispatch_uid="update_current_balance")
def update_current_balance(sender, **kwargs):
  created = kwargs['created']
  instance = kwargs['instance']
    if created:
      instance.current_balance = F('deposited_amount') + F('opening_balance')

创建新帐户效果很好,但current_balance不会更新。我在这里想念什么?

此外,我在考虑如果存款金额或期初余额已更新,我也需要更新当前余额,所以我应该删除if created支票,还是创建另一个信号? ?

1 个答案:

答案 0 :(得分:1)

您需要在信号中调用instance.save来更新实例。以下代码可以解决您的问题

@receiver(post_save, sender=Account, dispatch_uid="update_current_balance")
def update_current_balance(sender, **kwargs):
  created = kwargs['created']
  instance = kwargs['instance']
    if created:
      instance.current_balance = F('deposited_amount') + F('opening_balance')
      instance.save()
    elif 'deposited_amount' in  kwargs['updated_fields']:
      # do your work and don't forget to call .save()

或者您需要在pre_save信号中执行此操作。

更新TransactionLog

我们将有三个帐户。 User将保留有关帐户所有者的信息,UserAccount将保留有关用户当前有多少钱的信息。 TransactionLog将所有交易保留在我们的系统中。这样

  1. 这可以用作我们的Truth Table。如果用户不满,我的帐户中应该有很多钱(目前未显示)。我们可以给他发言。
  2. 我们可以区分责任。每个模型都应担负起单一的责任。

可能的模型

首先,我们应该有UserModel。这可以是Default Django User Mode link,也可以扩展AbstractBaseUser模型link

class Account(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    balance = models.BigIntegerField(default=0)


class TransactionLog(models.Model):
    CREDIT = 'CREDIT'
    DEBIT = 'DEBIT'
    OPENING_ACCOUNT = 'OPENING_ACCOUNT'
    DEPOSITE_INTO_ACCOUNT = 'DEPOSITE_INTO_ACCOUNT'
    WITHDRAW_FROM_ACCOUNT = 'WITHDRAW_FROM_ACCOUNT'
    UNKNOWN = 'UNKNOWN'
    TRANSACTION_TYPES = (
        (CREDIT, 'credit'),
        (DEBIT, 'debit'),
    )
    REASON_TYPES = ((OPENING_ACCOUNT, 'OPENING_ACCOUNT'), (DEPOSITE_INTO_ACCOUNT,
                                                     'deposite_into_account'),
                    (WITHDRAW_FROM_ACCOUNT, 'withDRAW_FROM_ACCOUNT'), (UNKNOWN, 'unknown'))

    type = models.CharField(choices=TRANSACTION_TYPES, max_length=6)
    reason = models.CharField(
        choices=REASON_TYPES, max_length=255, default=UNKNOWN)
    timestamp = models.DateTimeField(auto_now_add=True)
    amount = models.IntegerField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)

现在,对于系统中TransactionLog中的每个条目,我们将触发一个信号。基于reasontype,我们将更新Account。我必须提到opening accountdeposite first amount应该有所不同。 TransactionLog表中必须有其他条目。 TransactionLog是我们的Truth Log Table。这应该记录每个transaction

我们的信号将像

from .models import Account, TransactionLog

@receiver(post_save, sender=TransactionLog, dispatch_uid="transaction log entry")
def update_user_account(sender, instance, **kwargs):
    if instance.reason == TransactionLog.OPENING_ACCOUNT:  
        Account.objects.create(user=instance.user_id, balance=instance.amount) 
    else:
        user_account = Account.objects.get(user=instance.user_id)
        if instance.type == TransactionLog.CREDIT:
            user_account.balance = F('balance') + instance.amount
        else: # For Debit 
            user_account.balance = F('balance') - instance.amount

        user_account.save()

我想补充的一件事。由于这是我们模型中与交易相关的插入,因此TransactionLogAccount中的两个条目都应具有transaction_automic链。甚至我们都可以在模型设置link中执行此操作,以便我们所有的视图/ HTTP_REQUEST_API都应具有该功能。

希望这会有所帮助。