我们通过以下方式开发了在Django中进行软删除的快速方法:
在实践中运作良好,当传输被删除并且查询不返回时,隐藏传输。
唯一的问题是我们希望在另一个模型中被外键引用时仍然会显示这些内容。例如,事务模型引用了诸如transaction.transfer之类的Transfer,它现在是Django的None。
有什么想法吗?
答案 0 :(得分:0)
只要经理没有:
use_for_related_fields = True
作为类属性,外键查找
transaction.transfer
仍会填充模型实例。
此处要注意的另一件事是,您应该知道删除引用或被其他模型引用的模型对象需要进行精细处理,以便在调用delete
时不会意外丢失任何数据。
e.g。
删除通常的工作方式如下:
Transfer.objects.filter(id=my_id).delete()
--> Deletes all other objects related to it by default, sets to null if you like
但是如果你添加了软删除,那就是应用程序级逻辑,如果你这样做的话就是这样:
Transaction.objects.filter(id=another_id).delete()
您可能会无意中删除您不想删除的对象!
如果非软删除模型知道删除不合适,您应该没问题(设置空行为,覆盖模型类和模型管理器上的删除方法)。
供参考,请参阅使用pinax-models
完成的操作答案 1 :(得分:0)
我们最终解决了这个问题,只在我们只需要软对象时调用objects_soft ......这种方式相关的查找已经使用默认对象管理器并找到相关的fk。对于我们的多态模型,这最终成为:
objects = PolymorphicManager()
objects_soft = SoftPolymorphicObjectManager()
使用
查询它们TransferBase.objects_soft.filter()...
模型扩展了软删除功能:
class SoftDeleteFunctions(object):
def soft_delete(self):
self.deleted_on = now()
self.save()
class SoftPolymorphicObjectManager(PolymorphicManager):
def get_queryset(self):
queryset = self.queryset_class(self.model, using=self._db)
return queryset.filter(deleted_on=None)
class SoftObjectManager(Manager):
def get_queryset(self):
queryset = super(Manager, self).get_queryset()
return queryset.filter(deleted_on=None)
答案 2 :(得分:0)
除了@ kevin-parker的answer外,我还想根据文章Soft Deletion in Django中的想法保留这段代码。我进行了更改以支持多态模型,但是未测试此代码。改变了主意,使用django-polymorphic。
from django.db import models
from django.utils import timezone
from polymorphic.models import PolymorphicModel
from polymorphic.managers import PolymorphicManager
from polymorphic.query import PolymorphicQuerySet
class SoftPolymorphicQuerySet(PolymorphicQuerySet):
def delete(self):
return super().update(deleted_at=timezone.now())
def hard_delete(self):
return super().delete()
def alive(self):
return self.filter(deleted_at=None)
def dead(self):
return self.exclude(deleted_at=None)
class SoftPolymorphicDeletionManager(PolymorphicManager):
queryset_class = SoftPolymorphicQuerySet
def __init__(self, *args, **kwargs):
self.alive_only = kwargs.pop('alive_only', True)
super().__init__(*args, **kwargs)
def get_queryset(self):
qs = super().get_queryset()
if self.alive_only:
return qs.filter(deleted_at=None)
return qs
def hard_delete(self):
return self.get_queryset().hard_delete()
class SoftPolymorphicDeletionModel(PolymorphicModel):
deleted_at = models.DateTimeField(blank=True, null=True)
class Meta(PolymorphicModel.Meta):
abstract = True
objects = SoftPolymorphicDeletionManager()
all_objects = SoftPolymorphicDeletionManager(alive_only=False)
# For backward compatibility keep original arguments
def delete(self, *args, **kwargs):
self.deleted_at = timezone.now()
self.save()
# Pass arguments to original delete method
def hard_delete(self, *args, **kwargs):
super().delete(*args, **kwargs)