bugfix> python > 投稿

誰かが私がこの問題を解決するのを手伝ってもらえますか? 2つのモデルでdjangoアプリを作成しました。 1つのモデルはウォレットモデルで、もう1つはトランザクションモデルです。すべてのトランザクションは、models.ForeignKeyを使用してウォレットに接続されます。また、2つのシグナルを作成しました。1つはトランザクションが行われたときにウォレットの暗号通貨残高(BTC、ETHなど)を更新するためのもので、もう1つはTotal_Balance(USDに変換された他のすべての残高)を更新したい信号です。シグナルがPOST_SAVEであり、その中に無限ループを引き起こすsave()メソッドがあるため、ここで問題が発生します。最初のシグナルですべてを実行すると機能すると思いますが、将来的にはウォレットに接続される新しいモデルを追加したいと思います。これにより、total_balanceがポップアップ表示されるため、3番目のシグナルでも同じロジックが必要になります。そして、2つの信号で同じコードになってしまいます。

私の説明は少し厄介です。これはそれを理解するのに役立ついくつかのコードです。

私のモデル:

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()

回答 1 件
  • ザ・ post_save あなたの Wallet を実行します instance.save() 、つまり、 .save() 君の Wallet 、トリガーされます post_save の信号 Wallet これによりウォレットが再び保存されるため、シグナルが実行されるたびにウォレットが保存され、シグナルがトリガーされます。

    私が見る限り、あなたは使用する必要はありません 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はデータベースでレコードの作成/更新を開始します。

あなたの答え