Site Overlay

django1.11自定义模型model实现软删除(逻辑删除)

首先鸣谢:
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

至此,把各种程度的自定义软删除实现都讲解了,各位同学可以根据自己的需要,来选择使用了。

Leave a Reply

Your email address will not be published. Required fields are marked *