首先鸣谢:
https://blog.csdn.net/q1242027878/article/details/74906780
https://blog.csdn.net/anonymous_qsh/article/details/79838985
环境
Django 1.11
python:3.6
缘由
开发中,我们总是不能把数据之间删除,都是在一个字段里面做标记。
django orm的delete方法是直接删除,我们复写次方法可以实现。
如在app.model中这样实现:
class SomeModelDemo(models.Model):
created_at = models.DateTimeField("创建时间",auto_now_add=True)
updated_at = models.DateTimeField("更新时间",auto_now=True)
deleted_at = models.DateTimeField("删除时间",null=True,default=False)
def delete(self, using=None, keep_parents=False):
self.deleted_at = True
self.save()
但是呢,
1、每次都这样手动给表加一个字段,超级麻烦,也不优雅;
2、可能还是经常忘记查询数据的时候过滤default=True
,反复改来改去,费时费力。
so,
我们干脆参考两位同学的方法并增强,一次性到位。
实现
- 在根目录utils文件夹中创建一个
django_softdelete_model.py
from django.db import models
from django.db.models.query import QuerySet
# 自定义逻辑删除model类,Begin:
class SoftDeleteQuerySet(QuerySet):
def delete(self):
self.update(is_deleted=True)
class SoftDeleteManager(models.Manager):
"""
仅返回未被删除的实例
"""
_queryset_class = SoftDeleteQuerySet
def get_queryset(self):
"""
在这里处理一下QuerySet, 然后返回没被标记位is_deleted的QuerySet
"""
kwargs = {'model': self.model, 'using': self._db}
if hasattr(self, '_hints'):
kwargs['hints'] = self._hints
return self._queryset_class(**kwargs).filter(is_deleted=False)
class SoftDeleteModel(models.Model):
"""
抽象类,添加is_deleted 字段
"""
is_deleted = models.BooleanField(default=False)
class Meta:
abstract = True
objects = SoftDeleteManager()
def delete(self, using=None, soft=True, *args, **kwargs):
"""
这里需要真删除的话soft=False即可
"""
if soft:
self.is_deleted = True
self.save(using=using)
else:
return super(SoftDeleteModel, self).delete(using=using, *args, **kwargs)
# 自定义逻辑删除model类,End。
- 在应用中创建模型时,继承此自定义的
SoftDeleteModel
模型类,如:
from django.db import models
from extra_apps.utils.django_softdelete_model import SoftDeleteModel
from user.models import UserProfile
# Create your models here.
class CardStyle(SoftDeleteModel):
"""
名片样式表
"""
style_id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='样式id', help_text="名片样式id")
style_name = models.CharField(max_length=50, null=False, blank=False, verbose_name='样式名称', help_text="名片样式名称")
create_date = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_date = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
verbose_name = '名片样式' # 模型别名
verbose_name_plural = '样式管理' # 模型别名复数
db_table = 'card_style'
- makemigrations migrate 之后,数据库表都会默认加上
is_deleted
字段; - 在使用orm查询的时候,不会查询出
is_deleted=True
的数据; - 使用delete()方法的时候,不会删除数据,只是update
is_deleted=True
。