這將包裹從我的應用程序的實施方案。一些代碼的形式LWN's answer.
有你的數據被刪除4種情況:
- SQL查詢
- 對Model實例調用
delete()
:project.delete()
- 上查詢集innstance調用
delete()
:Project.objects.all().delete()
- 外地字段刪除其他型號
雖然第一種情況沒有什麼可以做,但其他三種可以進行細粒度控制。 一個建議是,在大多數情況下,您絕對不應該刪除數據本身,因爲這些數據反映了我們應用程序的歷史和使用情況。設置爲active
而不是布爾字段。
爲了防止Model實例,子類delete()
delete()
在模型聲明:
def delete(self):
self.active = False
self.save(update_fields=('active',))
雖然delete()
上查詢集實例需要用自定義對象管理一個小設置爲LWN's answer.
總結這部長達一個可重用的實現:
class ActiveQuerySet(models.QuerySet):
def delete(self):
self.save(update_fields=('active',))
class ActiveManager(models.Manager):
def active(self):
return self.model.objects.filter(active=True)
def get_queryset(self):
return ActiveQuerySet(self.model, using=self._db)
class ActiveModel(models.Model):
""" Use `active` state of model instead of delete it
"""
active = models.BooleanField(default=True, editable=False)
class Meta:
abstract = True
def delete(self):
self.active = False
self.save()
objects = ActiveManager()
用法,只是su bclass ActiveModel
類:
class Employee(models.Model):
name = models.CharField(name, unique=True)
class Project(models.Model):
name = models.CharField(name, unique=True)
manager = purchaser = models.ForeignKey(
Employee, related_name='project_as_manager')
>>> manager.delete() # this would cause `project` deleted as well
這是可以預防通過增加模型字段on_delete argument:
class Project(ActiveModel):
...
仍然是我們的目標仍然可以如果ForeignKey的領域中的任何一個被刪除刪除
class Project(models.Model):
name = models.CharField(name, unique=True)
manager = purchaser = models.ForeignKey(
Employee, related_name='project_as_manager',
on_delete=models.PROTECT)
on_delete
的缺省值是CASCADE
這將導致您的實例被刪除,通過使用PROTECT
取而代之的將會產生ProtectedError
(IntegrityError
的子類)。這樣做的另一個目的是數據的ForeignKey應該保留作爲參考。
這僅僅使用Python代碼是不可行的;數據庫本身也需要修改。 – 2011-01-28 07:32:41
感謝您的評論。我首先查找Python/Django部分,然後看看在我的應用程序中有多遠。 – dyve 2011-01-28 07:35:18