Djangoのpost_save信号を使用して、モデルを保存した後にいくつかのステートメントを実行しています。
class Mode(models.Model):
name = models.CharField(max_length=5)
mode = models.BooleanField()
from Django.db.models.signals import post_save
from Django.dispatch import receiver
@receiver(post_save, sender=Mode)
def post_save(sender, instance, created, **kwargs):
# do some stuff
pass
ここで、mode
フィールドの値が変更されたかどうかに基づいてステートメントを実行します。
@receiver(post_save, sender=Mode)
def post_save(sender, instance, created, **kwargs):
# if value of `mode` has changed:
# then do this
# else:
# do that
pass
いくつかのSOFスレッドとブログを見ましたが、これに対する解決策が見つかりませんでした。それらはすべて、私の使用例ではないpre_saveメソッドまたはフォームを使用しようとしました。 https://docs.djangoproject.com/es/1.9/ref/signals/#post-save in Django docsは直接的な方法について言及していないこれを行う。
以下のリンクの回答は有望に見えますが、使用方法がわかりません。最新のDjango=バージョンがこれをサポートしているかどうかはわかりません。これはipdb
を使用してこれをデバッグし、instance
変数に属性has_changed
以下の回答に記載されているとおり。
__init__
を使用して、モデルにアクセスできるようにします。
def __init__(self, *args, **kwargs):
super(YourModel, self).__init__(*args, **kwargs)
self.__original_mode = self.mode
これで、次のようなことができます。
if instance.mode != instance.__original_mode:
# do something useful
通常、信号を使用するよりもsaveメソッドをオーバーライドする方が適切です。
From Djangoの2つのスクープ :「最後の手段として信号を使用します。」
Initの元の値をキャッシュすることについて@scoopsevenの回答に同意しますが、可能であればsaveメソッドをオーバーライドします。
class Mode(models.Model):
name = models.CharField(max_length=5)
mode = models.BooleanField()
__original_mode = None
def __init__(self, *args, **kwargs):
super(Mode, self).__init__(*args, **kwargs)
self.__original_mode = self.mode
def save(self, force_insert=False, force_update=False, *args, **kwargs):
if self.mode != self.__original_mode:
# then do this
else:
# do that
super(Mode, self).save(force_insert, force_update, *args, **kwargs)
self.__original_mode = self.mode
これは古い質問ですが、最近この状況に遭遇しました。次のことを実行して達成しました。
class Mode(models.Model):
def save(self, *args, **kwargs):
if self.pk:
# If self.pk is not None then it's an update.
cls = self.__class__
old = cls.objects.get(pk=self.pk)
# This will get the current model state since super().save() isn't called yet.
new = self # This gets the newly instantiated Mode object with the new values.
changed_fields = []
for field in cls._meta.get_fields():
field_name = field.name
try:
if getattr(old, field_name) != getattr(new, field_name):
changed_fields.append(field_name)
except Exception as ex: # Catch field does not exist exception
pass
kwargs['update_fields'] = changed_fields
super().save(*args, **kwargs)
これは、アプリおよびDjango-adminからのすべての更新/保存をキャッチするため、より効果的です。
保存アクションの前後で状態を比較したい場合は、pre_save
データベース更新後になるはずのインスタンスを提供するシグナル。pre_saveでは、データベース内のインスタンスの現在の状態を読み取り、差異に基づいていくつかのアクションを実行できます。
from Django.db.models.signals import post_save, pre_save
from Django.dispatch import receiver
@receiver(pre_save, sender=MyModel)
def on_cahnge(sender, instance: MyModel, **kwargs):
if instance.id is None: # new object will be created
pass # write your code hier
else:
previous = MyModel.objects.get(id=instance.id)
if previous.field_a != instance.field_a: # fielad will be updated
pass # write your code hier