Порой возникает задача выполнить некоторые действия в момент, когда в модели произошло конкретное определённое изменение. В описанном примере рассматривается модель заказа, и нужно записать время оплаты заказа в момент, когда статус оплаты изменился с «не оплачено» на «оплачено». Сама модель:
class Order(models.Model):
user = models.ForeignKey(User)
paid = models.BooleanField(“оплачено”, default=False)
paid_time = models.DateTimeField(“время оплаты”, blank=True, null=True)
При создании заказа поле paid
принимает значение False
. При оплате через интегрированную с сайтом платёжную систему это поле устанавливается в True
. А также можно через админку вручную установить этот флажок. В любом случае должно записываться время этого действия.
Есть несколько способов выполнить задачу, включая сигналы и обработку во вьюхах или формах. Но рассмотрим решение испключительно на уровне модели.
Очевидно, что нужно переопределить метод save()
. И в нём нужно отследить случай, когда поле paid
было установлено в False
, а стало установлено в True
. Новое значение уже есть в self.paid
. Осталось получить старое.
Старое значение можно сохранить в отдельном поле при инициализации объекта, в методе __init__
. В итоге получим код:
class Order(models.Model):
user = models.ForeignKey(User)
paid = models.BooleanField(“оплачено”, default=False)
paid_time = models.DateTimeField(“время оплаты”, blank=True, null=True)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.was_paid = self.paid
def save(self, *args, **kwargs):
if self.paid and not self.was_paid:
self.paid_time = timezone.now()
return super().save(*args, **kwargs)