Python Django信号环
有人能帮我解决这个问题吗。我已经创建了一个带有两个模型的django应用程序。 一个模型是钱包模型,另一个是交易模型。每一笔交易都与models.ForeignKey钱包相连。我还创建了两个信号,一个是用于在进行交易时更新钱包中的加密货币余额(如BTC、ETH),另一个是我想要更新总余额(即所有其他余额转换为美元)。这里我有一个问题,因为我的信号是POST_SAVE,其中有一个SAVE()方法,它会导致无穷循环。我想,如果我在第一个信号中做一整件事,它会起作用,但在未来,我想添加新的型号,它也将连接到钱包,它将弹出我的总余额,因此,我需要在第三个信号中使用相同的逻辑,我将在两个信号中使用相同的代码 我知道我的描述有点混乱。下面是一些代码来帮助理解它 我的模型:Python Django信号环,python,django,django-models,django-signals,Python,Django,Django Models,Django Signals,有人能帮我解决这个问题吗。我已经创建了一个带有两个模型的django应用程序。 一个模型是钱包模型,另一个是交易模型。每一笔交易都与models.ForeignKey钱包相连。我还创建了两个信号,一个是用于在进行交易时更新钱包中的加密货币余额(如BTC、ETH),另一个是我想要更新总余额(即所有其他余额转换为美元)。这里我有一个问题,因为我的信号是POST_SAVE,其中有一个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()
您的
钱包的post\u save
执行一个实例.save()
,这意味着如果您.save()
您的钱包
,它将触发钱包
上的post\u save
信号,然后再次保存钱包,因此,每次信号运行时,它都会再次保存钱包,从而触发信号
据我所知,您不需要使用post_save
信号,因为您似乎不使用仅在保存对象后可用的任何内容。您可以使用将对象保存到数据库之前运行的pre_save
信号:
from django.db.models.signals import pre_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)
# no instance.save()
从django.db.models.signals导入预保存
@接收方(预存,发送方=钱包)
def总余额更新(发送方、实例,**kwargs):
如果instance.pk不是None:
btc_price=cryptocompare.get_price('btc',curr='USD')['btc']['USD']
xrp\u price=cryptocompare.get\u price('xrp',curr='USD')['xrp']['USD']
...
btc_balance=float(实例.btc_balance)
xrp\u balance=float(实例.xrp\u balance)
...
instance.total_balance=四舍五入(btc_balance*btc_price)+四舍五入(xrp_balance*xrp_balance)+四舍五入(eth_balance*eth_balance)
#没有实例。save()
因此,我们不需要保存实例
,因为在运行信号后,Django将立即开始在数据库中创建/更新记录。钱包
的后期保存
包含一个实例.save()
。这意味着,如果你.save()
一个钱包,信号将再次运行保存钱包(从而再次等等)是的,我知道,这就是我寻求帮助的原因。我能做些什么?谢谢,这很有效。但是对于记录,您需要删除“created”参数,因为pre_save确实需要它。@bazzuk123:aahh是的。您可以使用instance.pk而不是None
。将被更新的记录有一个.pk
不是None
。