Как добавить значение в поле в той же модели при сохранении модели - администратор django - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть модель 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_amount и opening_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 голосов
/ 05 февраля 2019

вам нужно позвонить 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 ссылка Или мы можем расширить AbstractBaseUser модель ссылка

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 в нашей системе мыподхватит сигнал.На основе reason и type мы обновим наш Account.Я должен отметить, что opening account и deposite 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()

Одна важная вещь, которую я хочу добавить.Поскольку в наших моделях это вставка, связанная с транзакцией, обе записи в TransactionLog и Account должны иметь цепочку transaction_automic.Даже мы можем сделать это в наших настройках модели ссылка , чтобы все наши представления / HTTP_REQUEST_API имели это.

Надеюсь, это поможет.

...