在这个问题中,它讨论了如何在处理相关对象时设置客户经理,但是答案发布到 Django 1 和 2。
在doco 的第 3 版中,它说在查询相关模型时不使用 Base 管理器。使用 default_manager_name 或 base_manager_name 对我们的相关查询没有影响。我们是否必须更新所有序列化以包含该过滤器,或者是否有其他管理器可以用来复制该功能?我们的问题在我们有deleted
标志的文档中是相同的。
在这个问题中,它讨论了如何在处理相关对象时设置客户经理,但是答案发布到 Django 1 和 2。
在doco 的第 3 版中,它说在查询相关模型时不使用 Base 管理器。使用 default_manager_name 或 base_manager_name 对我们的相关查询没有影响。我们是否必须更新所有序列化以包含该过滤器,或者是否有其他管理器可以用来复制该功能?我们的问题在我们有deleted
标志的文档中是相同的。
我的环境是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()
...