【问题标题】:Overriding delete() vs using pre delete signal覆盖 delete() 与使用预删除信号
【发布时间】:2018-08-28 08:37:16
【问题描述】:

我有一个模型,当一个对象被删除时,我想要一个模型,而不是被删除,而是更新状态。这是通过以下代码实现的:

def delete(self, using=None, keep_parents=False):
    self.status = Booking.DELETED
    self.save()

管理器已更新,因此在应用程序的其余部分中,我永远不会收到已删除的预订。

class BookingManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().exclude(status=Booking.DELETED)

class BookingDeletedManager(models.Manager):
    def get_queryset(self):
         return super().get_queryset().filter(status=Booking.DELETED)

class Booking(models.Model):
    PAYED = 0
    PENDING = 1
    OPEN = 2
    CANCELLED = 3
    DELETED = 4
    objects = BookingManager()
    deleted_objects = BookingDeletedManager()
...  

现在我已经阅读了 django 信号,想知道在这里使用预删除信号是否更好。可以更改代码,以便在预删除接收器中创建一个状态为“已删除”的副本,而原始预订被删除。

documentation 中声明这些信号应该用于当框架中的其他地方发生操作时,允许解耦的应用程序得到通知。似乎信号是一个很好的解决方案,但文档中的这种细微差别让我认为这可能不是我想要的,而覆盖可能只是要走的路。

这里并非如此,因为我一直都想要这个功能。 所以我的问题是有充分的理由为什么我不应该覆盖删除方法并使用预删除信号,反之亦然?

【问题讨论】:

    标签: python django django-models orm


    【解决方案1】:

    在文档中指出,当框架中的其他地方发生操作时,应该使用这些信号来通知解耦应用程序。

    这确实是重点:允许一个应用程序收到另一个应用程序中发生的事件的通知对第一个应用程序一无所知 - 因此避免了将第二个应用程序耦合到第一个应用程序的需要。

    在你的情况下,使用模型信号而不是仅仅覆盖模型的方法将是an anti-pattern:它只会增加开销并使你的代码不那么可读,绝对没有充分的理由,当非常明显的解决方案是做你想做的事情时有过。

    【讨论】:

    • 请注意,在批量操作docs.djangoproject.com/en/dev/topics/db/models/… 上不会调用重写的模型方法。但是,当使用 pre_delete 信号时,无法停止删除。我不确定绕过这个的正确方法是什么。
    • @gabn88 请注意,在原始 sql 查询或在 orm / 项目之外进行的查询都不会调用信号 ;-) - 如果您想要始终执行的某些内容,但是该行被删除,您想要一个数据库触发器。
    猜你喜欢
    • 2010-09-15
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 2010-12-04
    相关资源
    最近更新 更多