Django Пользовательский менеджер для обратного поиска внешних ключей (связанный менеджер) - PullRequest
0 голосов
/ 02 апреля 2020

Я использую пользовательский Менеджер моделей для Soft-Deletion и хочу сделать обратный поиск Foreignkey (Related Manager).

Менеджер:

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! = Нет. Как получить только живые предметы?

Заранее спасибо!

1 Ответ

0 голосов
/ 02 апреля 2020

При вызове user.sowi_set.all() ваш менеджер автоматически инициализируется на django с пустым параметром. Чтобы решить эту проблему, я искал способы передачи параметров, когда django инициализирует менеджер. Затем я нашел этот вопрос .

Вы должны изменить код следующим образом.

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()

...