django软删除与模型字段复用

之前使用TP,框架自带有软删除功能,如果使用django,虽然没有内置,我们也可以来简单的手写一下。想到这里权衡下,我们几乎所有的表都要用到这个字段甚至多个字段,当然我们可以不厌其烦的每个模型单独创建下,我们也可以使用代码复用的思想来完成这件事。

模型字段复用

需要复用的字段有:

1
2
3
create_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)
update_time = models.DateTimeField(verbose_name='更新时间', auto_now=True)
delete_time = models.DateTimeField(verbose_name='删除时间', null=True, blank=True)

模型类都有一个元属性,有一个关键字叫abstract,如果将该属性设置为True,数据库将不再创建该表。然而我们可以利用其来做父类,继承过来所有的模型不就自带这些字段了吗。

1
2
3
4
5
6
7
8
9
10
11
12
class SoftDeleteModel(models.Model):
create_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)
update_time = models.DateTimeField(verbose_name='更新时间', auto_now=True)
delete_time = models.DateTimeField(verbose_name='删除时间', null=True, blank=True)
class Meta:
abstract = True

class CatsModel(SoftDeleteModel):
name = models.CharField(max_length=25, verbose_name='名称')
remark = models.CharField(max_length=200, verbose_name='备注', blank=True)
def __str__(self):
return self.name

如此,CatsModel数据表中变自带了三个字段,其他模型同理。

Django软删除

软删除也要用到字段复用,默认delete_timeNull,删除时该字段为当前删除时间,这样就形成了软删除。

网上有的说在模型里直接重写delete方法,即可完成自定义软删除,我们来分析下我们的删除命令:

1
TableModel.objects.filter(pk=2).delete()

可以看到是走了一个objects的东西,如果你尝试过在模型类中重写delete方法你会发现,这条命令根本不会走你自己的delete方法。

objects是什么

默认情况下,Django 为每个Django模型类添加一个模型管理类Manager的对象为objects。如果想要将这个对象修改为其他名称,那么可以用models.Manager()来自定义创建对象

1
2
3
4
5
6
7
8
9
10
class AREA(models.Model):
....
area_obj = models.Manager() # 自定义模型管理对象

class Meta:
db_table = 'AREA' # 设置表名为 AREA

# 此时执行数据库操作,我们就可以不用objects了
AREA.area_obj.filter(pk=2).first()
AREA.area_obj.filter(pk=2).delete()

软删除示例

创建自定义manager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from django.db import models
from django.db.models.query import QuerySet
from django.utils import timezone
# 重写delete
class SoftDeleteQuerySet(QuerySet):
def delete(self):
self.update(delete_time=timezone.now())

# 重写manager,并重置查询筛选未删除记录
class SoftDeleteManager(models.Manager):
_queryset_class = SoftDeleteQuerySet

def get_queryset(self):
kwargs = {'model':self.model, 'using':self._db}
if hasattr(self, '_hints'):
kwargs['hints'] = self._hints
return self._queryset_class(**kwargs).filter(delete_time__isnull=True)

# 软删除模型类
class SoftDeleteModel(models.Model):
create_time = models.DateTimeField(verbose_name='添加时间', auto_now_add=True)
update_time = models.DateTimeField(verbose_name='更新时间', auto_now=True)
delete_time = models.DateTimeField(verbose_name='删除时间', null=True, blank=True)
class Meta:
abstract = True
objects = SoftDeleteManager()

继承软删除模型

1
2
3
4
5
class CatsModel(SoftDeleteModel):
name = models.CharField(max_length=25, verbose_name='名称')
remark = models.CharField(max_length=200, verbose_name='备注', blank=True)
def __str__(self):
return self.name

以上即完成了软删除的功能,迁移下数据库测试数据,看是否达到你想要的了!!!