Django сигналы не обновляют связанную модель при обновлении внешнего ключа - PullRequest
2 голосов
/ 20 апреля 2020

Я хочу обновлять связанную модель каждый раз, когда внешний ключ изменяется с помощью сигналов, аналогично m2m_changed, но для внешнего ключа.

Модель пользователя:

class User(AbstractUser):
    balance = models.FloatField(default=0)

Модель транзакции:

class Transaction(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='transactions')
    order = models.OneToOneField('Payment.Order', on_delete=models.CASCADE, related_name='transaction')
    transaction_type = models.CharField(choices=[
        ('transfer', 'Transfer'),
        ('received', 'Received'),
    ], max_length=20, default='transfer')
    created = models.DateTimeField(auto_now_add=True)

Мне нужно, чтобы при создании новой транзакции под пользователем она собиралась на баланс.

Сигнальный код:

@receiver(pre_save, sender=User)
    def collect_transaction(sender, instance, **kwargs):
    balance = instance.transactions.aggregate(Sum('order__price'))
    print(balance)

, но работает, только когда я обновляю его из модели User, а не Transaction .

Например, этот код заставит сигналы работать:

user.transactions.add(transaction)
user.save()

Принимая во внимание, что этот код не будет работать сигналам:

Transaction.objects.create(user=1, order=1, transaction_type='received')

1 Ответ

1 голос
/ 20 апреля 2020

Ваш сигнал будет отправлен только после сохранения модели User. Кажется, вы хотите, чтобы он был отправлен при сохранении любого Transaction, поэтому вы должны попытаться использовать Transaction в качестве отправителя вместо пользователя:

@receiver(post_save, sender=Transaction)
def collect_transactions(sender, instance, **kwargs):
    user = instance.user
    user.balance = user.transactions.aggregate(Sum('order__price'))
    user.save()

Что касается вашего исходного примера получения сигнала, когда Пользователь сохранен, я пытаюсь вспомнить случай, когда вы обновляете пользователя, но не обновляете связанные с ним транзакции, и все же необходимо обновить баланс. Если такой случай существует, вам может быть лучше переопределить метод save() в модели User.

...