Django Python 3.x - OneToOneField 使用 ContentTypes 覆盖 delete()

Django Python 3.x - OneToOneField override delete() with ContentTypes

场景:有不同的服务类型,即clothes_washing、room_cleaning和room_maintenance。 这些服务中的每一个都有共同的领域,例如 service_date。

根据场景,我有每个服务的模型和一个带有公共字段的 Service 模型。 Service模型与各服务模型的关系为OneToOneField.

我已经尝试在 Service 模型中重写 delete() 函数 answer 并且它适用于我,但仅适用于一项服务(如 [=18= 中的轮子) ]).但是如果我想删除服务类型?如何实现该方法?

我的models.py:

class ClothesWashing(models.Model):
    # special fields for clothes_washing
    service = models.OneToOneField(Service, on_delete=models.DO_NOTHING, null=True)

class RoomCleaning(models.Model):
    # special fields for room_cleaning 
    service = models.OneToOneField(Service, on_delete=models.DO_NOTHING, null=True)

class Service(models.Model):
    # common fields for all services

    def delete(self, *args, **kwargs):
        #here I wanna "roomcleaning" attribute to be dynamic upon content type
        self.roomcleaning.delete()
        return super(self.__class__, self).delete(*args, **kwargs)

您可以将on_delete参数设置为CASCADE:

class ClothesWashing(models.Model):
    # special fields for clothes_washing
    service = models.OneToOneField(Service, <b>on_delete=models.CASCADE</b>, null=True)

class RoomCleaning(models.Model):
    # special fields for room_cleaning 
    service = models.OneToOneField(Service, <b>on_delete=models.CASCADE</b>, null=True)

on_delete=… parameter [Django-doc] 指定当它引用的项目被删除时应该发生什么。因此,如果 Service 被删除,并且有一个 ClothesWashing 模型引用它,那么您可以指定要做什么。

通过使用 CASCADE [Django-doc],您还将删除相关的 ClothesWashing 对象,或者按照文档中的说明:

Cascade deletes. Django emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey.

最好用这个触发器来实现它,因为像 .delete() 这样的方法 而不是 在批量删除时总是由 ORM 调用。因此 Service.objects.all().delete() 将删除所有服务,但 永远不会 调用您的 Service.delete() 方法。通过定义触发器,您可以向 Django 指定与其相关的项目应该发生什么。

在这种特定情况下,您可能希望使用 model inheritance [Django-doc]。 Django 可以自己实现一些样板逻辑(比如 OneToOneFields 到父模型等)。

编辑:如果要删除给定的 ClothesWashingRoomCleaning 等服务,则可以覆盖 .delete() 方法也可以删除那个,例如,您可以创建一个抽象基础 class :

class ServiceBase(models.Model):
    # special fields for clothes_washing
    service = models.OneToOneField(Service, on_delete=models.CASCADE, null=True)

    def delete(self, *args, **kwargs):
        service = self.service
        super().delete(*args, **kwargs)
        self<b>.service.delete()</b>

    class Meta:
        <b>abstract = True</b>

class ClothesWashing(<b>ServiceBase</b>):
    # …
    pass

class RoomCleaning(<b>ServiceBase</b>):
    # …
    pass

但是,如果您使用 ORM,最终可能不会删除某些对象,因为上述方法可以避免这种情况。