Reputation: 661
I have 2 models: Transaction and Wallet, a wallet has multiple transactions.
I need to update the amount
field in Wallet
model whenever a new transaction is created. The way I see is overwrite save
method in the model. Currently, I wrote like this
def save(self, *args, **kwargs):
if self.kind == "Income":
self.wallet.amount += self.amount
elif self.kind == "Outcome":
self.wallet.amount -= self.amount
self.wallet.save()
super(Transaction, self).save(*args, **kwargs)
It creates a new transaction correctly but not update the wallet model. How I can fix that?
Upvotes: 0
Views: 236
Reputation: 16
Did you check to see that your conditional statements are getting triggered?
This should actually work without you having to call self.wallet.save() if you have already passed a valid Wallet object to the Transaction.
def save(self, *args, **kwargs):
if self.kind == "Income":
self.wallet.amount += self.amount
elif self.kind == "Outcome":
self.wallet.amount -= self.amount
super(Transaction, self).save(*args, **kwargs)
See: https://docs.djangoproject.com/en/3.1/topics/db/queries/#saving-changes-to-objects
For information on how to save Object references.
So I think two things could be going wrong. Either your conditional statements are not getting triggered, or you are not passing a valid Wallet Object reference to the Transaction.
Either way...I think this is a good use case for Django's signals. First, I would remove the save method you have, and in the Transaction model I would add
def update_transaction_wallet(sender, instance, **kwargs):
if instance.kind == "Income":
instance.wallet.amount += instance.amount
elif instance.kind == "Outcome":
instance.wallet.amount -= instance.amount
signals.post_save.connect(update_transaction_wallet, sender=Transaction)
You may have to tweak this a bit in order for it to work in your specific case. You didn't provide a lot of information about your models and situation.
But basically, this bit of code tells Django that whenever a Transaction Objects gets saved to also run the update_transaction_wallet() method. See: https://docs.djangoproject.com/en/3.0/topics/signals/
Upvotes: 0
Reputation: 826
You should not be doing this because that information can be accessed via aggregate functions. Check out on django documentation.
But, if for some specific reason you you need to do it, you need to do it after the transaction is saved, with F expression:
from django.db.models import F
def save(self, *args, **kwargs):
super(Transaction, self).save(*args, **kwargs)
if self.kind == "Income":
self.wallet.amount = F('amount') + self.amount
elif self.kind == "Outcome":
self.wallet.amount = F('amount') - self.amount
self.wallet.save()
Upvotes: 1
Reputation: 302
You have to instantiate Wallet and then make the proper addition or subtraction on it.
I would do it inside a Transaction method, which you will call on save or any other place. and if saves fail, rowback the wallet amount too ;)
Upvotes: 0