1

在这个问题中,它讨论了如何在处理相关对象时设置客户经理,但是答案发布到 Django 1 和 2。

doco 的第 3 版中,它说在查询相关模型时不使用 Base 管理器。使用 default_manager_name 或 base_manager_name 对我们的相关查询没有影响。我们是否必须更新所有序列化以包含该过滤器,或者是否有其他管理器可以用来复制该功能?我们的问题在我们有deleted标志的文档中是相同的。

4

1 回答 1

0

我的环境是Django3.2.6+sqlite+Python3.8:

# crossover/models.py
from django.db import models


class SoftDeleteQuerySet(models.QuerySet):
    def delete(self):
        return self.update(deleted=True)

    def force_delete(self):
        return super().delete()


class FilteDeletedManager(models.Manager):
    def datas(self):
        return SoftDeleteQuerySet(self.model, self._db)

    def get_queryset(self):
        return SoftDeleteQuerySet(self.model, self._db).filter(deleted=False)


class AbsModel(models.Model):
    objects = FilteDeletedManager()
    deleted = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def delete(self, **kwargs):
        self.deleted = True
        return self.save(**kwargs)

    def force_delete(self, **kwargs):
        return super().delete(**kwargs)

    def to_dict(self):
        return {f.name: getattr(self, f.name) for f in self._meta.fields}

    class Meta:
        abstract = True


class Player(AbsModel):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

用法::

>>> from crossover.models import *
>>> p1, p2 = Player.objects.create(name='LBJ'), Player.objects.create(name='KD')
>>> Player.objects.all()
<SoftDeleteQuerySet [<Player: LBJ>, <Player: KD>]>
>>> Player.objects.filter(id=1).delete()
1
>>> Player.objects.all()
<SoftDeleteQuerySet [<Player: KD>]>
>>> Player.objects.datas()
<SoftDeleteQuerySet [<Player: LBJ>, <Player: KD>]>
>>> p2.delete()
>>> Player.objects.all()
<SoftDeleteQuerySet []>
>>> Player.objects.datas()
<SoftDeleteQuerySet [<Player: LBJ>, <Player: KD>]>
>>> p1.force_delete()
(1, {'crossover.Player': 1})
>>> Player.objects.datas()
<SoftDeleteQuerySet [<Player: KD>]>
>>> Player.objects.datas().force_delete()
(1, {'crossover.Player': 1})
>>> Player.objects.datas()
<SoftDeleteQuerySet []>

关于 ForeignKey 字段:标记为已删除时,将其子字段也标记为已删除。

from django.db.models.deletion import Collector

class MyCollector(Collector):
    def delete(self):
        ...
        with transaction.atomic(using=self.using, savepoint=False):
            # update deleted=True

class AbsModel(models.Model):
    def delete(self, using=None, keep_parents=False):
        using = using or router.db_for_write(self.__class__, instance=self)
        assert self.pk is not None
        collector = MyCollector(using=using)
        collector.collect([self], keep_parents=keep_parents)
        return collector.delete()
     ...
于 2021-09-24T03:43:45.367 回答