Django信号环路



有人能帮我解决这个问题吗。我创建了一个有两个模型的django应用程序。一个模型是钱包模型,另一个是交易模型。每笔交易都连接到一个带有模型的钱包中。ForeignKey。我还创建了两个信号,一个是在交易时更新钱包中的加密货币余额(如BTC、ETH(,另一个信号是我想更新Total_balance(即所有其他余额转换为美元(。这里我有一个问题,因为我的信号是POstrongAVE,其中有一个SAVE((方法,它会导致无限循环。我想如果我在第一个信号中做一整件事,它会起作用,但将来我想添加一个新的模型,它也会连接到钱包,它会弹出我的总余额,因此我在第三个信号中需要相同的逻辑,我最终会在两个信号中使用相同的代码。

我知道我的描述有点混乱。这里有一些代码可以帮助理解它

我的型号:

class Wallet(models.Model):
name = models.CharField(max_length=50)
total_balance = models.IntegerField(blank=True)
btc_balance = models.DecimalField(max_digits=15, decimal_places=8)
xrp_balance = models.DecimalField(max_digits=15, decimal_places=8)
eth_balance = models.DecimalField(max_digits=15, decimal_places=8)
class Transaction(models.Model):
wallet = models.ForeignKey(Wallet, on_delete=models.CASCADE)
currency_paid = models.CharField(choices=CURRENCY, max_length=3)
amount_paid = models.DecimalField(max_digits=15, decimal_places=8)
currency_recived = models.CharField(choices=CURRENCY, max_length=3)
amount_recived = models.DecimalField(max_digits=15, decimal_places=8)

我的信号:

@receiver(post_save, sender=Transaction)
def create_transaction(sender, instance, created, **kwargs):
if created:
wallet = Wallet.objects.get(name = instance.wallet)
currency_paid = instance.currency_paid
currency_recived = instance.currency_recived
amount_paid = instance.amount_paid
amount_recived = instance.amount_recived
# SUBSTRACK BALANCE
if(currency_paid == 'BTC'):
wallet.btc_balance -= amount_paid
...
# ADDS BALANCE
if(currency_recived == 'BTC'):
wallet.btc_balance += amount_recived
...
wallet.save()

@receiver(post_save, sender=Wallet)
def total_balance_update(sender, instance, created, **kwargs):
if created == False:
btc_price = cryptocompare.get_price('BTC',curr='USD')['BTC']['USD']
xrp_price = cryptocompare.get_price('XRP',curr='USD')['XRP']['USD']
...

btc_balance = float(instance.btc_balance)
xrp_balance = float(instance.xrp_balance)
...

total_balance = instance.total_balance
total_balance = round(btc_balance * btc_price) + round(xrp_balance * xrp_balance) + round(eth_balance * eth_balance)
instance.save()

Walletpost_save执行instance.save(),这意味着如果您.save()您的Wallet,它将触发Wallet上的post_save信号,然后再次保存钱包,因此每次信号运行时,它都会再次保存钱包触发信号。

然而,据我所见,您不需要使用post_save信号,因为您似乎不使用任何仅在对象保存后可用的。您可以使用pre_save信号,该信号将在将对象保存到数据库之前运行

from django.db.models.signals importpre_save
@receiver(pre_save, sender=Wallet)
def total_balance_update(sender, instance, **kwargs):
if instance.pk is not None:
btc_price = cryptocompare.get_price('BTC',curr='USD')['BTC']['USD']
xrp_price = cryptocompare.get_price('XRP',curr='USD')['XRP']['USD']
...

btc_balance = float(instance.btc_balance)
xrp_balance = float(instance.xrp_balance)
...
instance.total_balance = round(btc_balance * btc_price) + round(xrp_balance * xrp_balance) + round(eth_balance * eth_balance)
#noinstance.save()

因此,我们不需要保存instance,因为在运行信号后,Django将立即开始在数据库中创建/更新记录。

最新更新