Django ORM 中触发字段如何变化

How trigger field changes in Django ORM

我有一个用 Django 编写的项目。在我使用 SQLAlchemy 的另一个项目中,我使用非常有用的方法来触发字段更改:

@event.listens_for(ClassName.field_name, 'set')
def func_name(target, value, oldvalue, initiator):
    if value == oldvalue:
        return

在我的 Django 项目中我有 Order class:

class Order(models.Model):
    PAYMENT_CHOICES = (
        ('Paid', 'Paid'),
        ('Not Paid', 'Not Paid')
    )
    EXECUTION_CHOICES = (
        ('Done', 'Done'),
        ('In Progress', 'In Progress')
    )
    name = models.CharField(max_length=255, default='')
    skype = models.CharField(max_length=255, default='')
    email = models.CharField(max_length=255, default='')
    status_of_execution = models.CharField(max_length=255, choices=EXECUTION_CHOICES, default='In Progress')
    status_of_payment = models.CharField(max_length=255, choices=PAYMENT_CHOICES, default='Not Paid')
    client_comment = models.TextField(blank=True, null=True)
    admin_comment = models.TextField(blank=True, null=True)
    total_price = models.IntegerField(null=False, blank=False, default=0)

    buyer = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True)

status_of_execution 字段仅在管理面板中更改,所以我想在该字段更改时触发,并在值 Done 发生更改时执行某些操作。但我没有找到像 SQLAlchemy 那样的解决方案,因为 Django 只有像“pre_savepost_save ...”这样的信号。

谁能知道如何使用 Django ORM 解决我的问题?

在 Django 中使用 pre_save 信号。

from django.dispatch import receiver
from django.db.models.signals import pre_save


@receiver(pre_save, sender=Order)
def event_handler(instance, **kwargs):

        old_instance = Order.objects.get(id=instance.id)
    except Order.DoesNotExist:
        # Created not Updated
        return 

    if instance.status_of_execution != old_instance.status_of_execution:
        print('status_of_execution changed')

如果它仅在管理员中更改,您可以覆盖管理员上的 save_model 并检查表单的 changed_data 列表:

class OrderAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        if 'status_of_execution' in form.changed_data:
            if form.cleaned_data['status_of_execution'] == 'Done':
                # do stuff
        return super().save_model(request, obj, form, change)