Как повысить DoNotExist - Django SoftDelete? - PullRequest
2 голосов
/ 02 апреля 2019

У меня есть абстрактная модель SoftDelete, как показано ниже.

class SoftDeleteManager(models.Manager):

    def get_queryset(self):
        return super().get_queryset().filter(is_deleted=False)

class SoftDeleteModel(models.Model):
     is_deleted = models.BooleanField(default=0)
     deleted_at = models.DateTimeField(null=True)

     objects = SoftDeleteManager()

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

     class Meta:
        abstract = True

class Employee(SafeDeleteModel):
   pass

При удалении модели я устанавливаю is_deleted на True и обновляю отметку времени deleted_at, а также создаю собственный менеджер для переопределения начальногонабор запросов, который возвращает только не удаленные поля (is_deleted = False).

employee = Employee.objects.get(pk=1)
employee.delete()
employee.refresh_from_db() // not raising DoesNotExist

Но допустим, у меня есть модель Employee, которая использует SafeDeleteModel для мягкого удаления, после удаления модели, такой как Employee.objects.get(pk=1).delete()когда я вызываю employee.refresh_from_db(), это не вызывает DoesNotExist, но обновляет значение is_deleted, dele_at, как и ожидалось, какую ошибку я здесь сделал, почему она не вызывает DoesNotExist?

1 Ответ

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

В Django 2.1 произошли изменения : refresh_from_db() теперь использует _base_manager модели, а не _default_manager, как для связанных запросов. Это гарантирует, что объект может быть обновлен, даже если он не найден менеджером по умолчанию.

Таким образом, вы должны установить SoftDeleteManager в качестве базового менеджера, используя base_manager_name. Но обратите внимание на этот комментарий:

Менеджеры баз не используются при запросах к связанным моделям. Например, если модель Question из учебника имеет поле deleted и базовый менеджер, который отфильтровывает экземпляры с помощью deleted=True, набор запросов, такой как Choice.objects.filter(question__name__startswith='What'), будет включать варианты, связанные с удаленными вопросами.

Кроме того, я не знаю, как вы извлечете любой объект, который был удален после внесения этого изменения, за исключением случаев, когда вы делаете специальный менеджер для не фильтрации удаленных объектов (например, deleted_objects) .

Обратите внимание, что я ожидаю, что пакет safedelete , о котором вы упоминали в своих комментариях, будет иметь ту же проблему, поскольку он также не изменит _base_manager.

...