首页 > 解决方案 > 用于反向外键查找的 Django 自定义管理器(相关管理器)

问题描述

我正在使用自定义模型管理器进行软删除,并希望进行反向外键查找(相关管理器)。

管理者:

class SoftDeletionQuerySet(QuerySet):
    def delete(self):
        return super(SoftDeletionQuerySet, self).update(deleted_at=timezone.now())

    def hard_delete(self):
        return super(SoftDeletionQuerySet, self).delete()

    def alive(self):
        return self.filter(deleted_at=None)

    def dead(self):
        return self.exclude(deleted_at=None)


class SoftDeletionManager(models.Manager):
    use_for_related_fields = True

    def __init__(self, *args, **kwargs):
        self.status = kwargs.pop("status", "all")
        super(SoftDeletionManager, self).__init__(*args, **kwargs)

    def get_queryset(self):
        if self.status == "alive":
            return SoftDeletionQuerySet(self.model).filter(deleted_at=None)
        elif self.status == "dead":
            return SoftDeletionQuerySet(self.model).exclude(deleted_at=None)
        else:
            return SoftDeletionQuerySet(self.model)

    def hard_delete(self):
        return self.get_queryset().hard_delete()



class SoftDeletionModel(models.Model):
    deleted_at = models.DateTimeField(blank=True, null=True)

    objects = SoftDeletionManager(status="alive")
    dead_objects = SoftDeletionManager(status="dead")
    all_objects = SoftDeletionManager()

    class Meta:
        abstract = True

    def delete(self):
        self.deleted_at = timezone.now()
        self.save()

    def hard_delete(self):
        super(SoftDeletionModel, self).delete()

用于模型:

class Sowi(SoftDeletionModel):
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

现在,对于给定的user,我想得到他的user.sowi_set,但只有那些“活着”的 SoWi。“正常”user.sowi_set还返回已死的元素,即具有deleted_at值!= 无。我如何只获得活着的对象?

提前致谢!

标签: pythondjangodjango-modelsdjango-views

解决方案


调用时user.sowi_set.all(),您的管理器将由 django 使用空参数自动初始化。为了解决这个问题,我在django初始化manager时寻找了传递参数的方法。然后,我发现了这个问题

您必须像这样更改代码。

def manager_factory(status=None):
    class SoftDeletionManager(models.Manager):
        deletion_status = status
        use_for_related_fields = True

        def get_queryset(self):
            if self.deletion_status == "alive":
                return SoftDeletionQuerySet(self.model).filter(deleted_at=None)
            elif self.deletion_status == "dead":
                return SoftDeletionQuerySet(self.model).exclude(deleted_at=None)
            else:
                return SoftDeletionQuerySet(self.model)

        def hard_delete(self):
            return self.get_queryset().hard_delete()
    return SoftDeletionManager()


class SoftDeletionModel(models.Model):
    deleted_at = models.DateTimeField(blank=True, null=True)

    objects = manager_factory("alive")
    dead_objects = manager_factory("dead")
    all_objects = manager_factory()

    class Meta:
        abstract = True

    def delete(self):
        self.deleted_at = timezone.now()
        self.save()

    def hard_delete(self):
        super(SoftDeletionModel, self).delete()


推荐阅读