[PYTHON] Logical deletion in Django, DRF (Django REST Framework)

Aside from the good and bad stories of logical deletion, in financial systems etc., any past data should not be deleted in the physical history (for a certain period of time), and logical deletion may be used. I've seen some articles on how to implement logical deletion in DRF, but since we implemented it this way, we'll take the plunge and publish it.

Model for logical deletion

class XQuerySet(models.QuerySet):
    def get_or_none(self, *args, **kwargs):
        try:
            return super(XQuerySet, self).get(*args, **kwargs)
        except ObjectDoesNotExist:
            return None

    def delete(self):
        """
Logical deletion
        Model.objects.all().delete()
        :return:
Number of deleted cases
        """
        return super(XQuerySet, self).update(is_active=False, deleted=now_tz())

    def delete_hard(self):
        """
Physical deletion
        Model.objects.all().delete_hard()
        :return:
Number of deleted cases
        """
        return super(XQuerySet, self).delete()


class XModelManager(models.Manager):
    def get_or_none(self, **kwargs):
        try:
            return self.get(**kwargs)
        except ObjectDoesNotExist:
            return None

    def get_queryset(self):
        return XQuerySet(self.model)


class XModelManagerActive(XModelManager):
    def get_queryset(self):
        return XQuerySet(self.model).filter(is_active=True)


class XModel(TimeStampedModel):
    is_active = models.BooleanField(
        default=True,
        editable=False,
        help_text="Flag for logical deletion"
    )

    deleted = models.DateTimeField(
        null=True,
        default=None,
        editable=False,
        help_text="Logically deleted time"
    )

    """
Manager used for normal search
What was logically deleted is not displayed
    """
    objects = XModelManagerActive()
    """
Manager used for global search
Display including logically deleted ones
    """
    entire = XModelManager()

    def delete(self, using=None, keep_parents=False, is_hard=False):
        if is_hard:
            return super().delete(using, keep_parents)
        else:
            self.deleted = now_tz()
            self.is_active = False
            self.save(using)
            return 1, {}

    def delete_hard(self, using=None, keep_parents=False):
        self.delete(using, keep_parents, is_hard=True)

    class Meta:
        abstract = True

I made two ModelManagers and used them properly, but since the basic (usually used) is ʻobjects`, it is a mechanism that logically deletes without the programmer being aware of it.

Actual model

class Category(XModel):
    name = models.CharField(
        max_length=32,
        null=False,
        blank=False,
        default="",
        help_text="Category name"
    )

    key = models.CharField(
        max_length=32,
        null=False,
        blank=False,
        default="",
        help_text="Category name English"
    )

It just inherits from XModel. It also comes with get_or_none.

For example, if you want to access the data that was logically deleted by Admin etc., you can do this

@admin.register(Category)
class AdminUserAdmin(admin.ModelAdmin):
    list_display = ('key', 'name')

    def get_queryset(self, request):
        return self.model.entire.all()

XTech uses the Django REST framework to develop the API. We have a lot of extensions that can reach the itchy part of the DRF, so I'd like to publish it as much as possible, so stay tuned.

Recommended Posts

Logical deletion in Django, DRF (Django REST Framework)
Django REST framework basics
Django Rest Framework Tips
Implement JWT login functionality in Django REST framework
Implementing authentication in Django REST Framework with djoser
List method for nested resources in Django REST framework
Django REST framework stumbling block
Django REST framework with Vue.js
Login with django rest framework
Implement hierarchical URLs with drf-nested-routers in Django REST framework
How to write custom validations in the Django REST Framework
[Django] Use MessagePack with Django REST framework
Implementation of JWT authentication functionality in Django REST Framework using djoser
Create RESTful APIs with Django Rest Framework
Understand the benefits of the Django Rest Framework
ng-admin + Django REST framework ready-to-create administration tool
CRUD GET with Nuxt & Django REST Framework ②
Miscellaneous notes about the Django REST framework
CRUD POST with Nuxt & Django REST Framework
CRUD GET with Nuxt & Django REST Framework ①
Django REST Framework + Clean Architecture Design Consideration
Implementation of custom user model authentication in Django REST Framework with djoser
How to deal with garbled characters in json of Django REST Framework
CRUD PUT, DELETE with Nuxt & Django REST Framework
Models in Django
Django REST framework A little useful to know.
How to create a Rest Api in Django
Forms in Django
Sometimes you want to access View information from Serializer with DRF (Django REST Framework)
Learning notes for the migrations feature in the Django framework (2)
Create a Todo app with Django REST Framework + Angular
More new user authentication methods with Django REST Framework
Create a Todo app with the Django REST framework
Create APIs around user authentication with Django REST Framework
When you want to filter with Django REST framework
Implement APIs at explosive speed using Django REST Framework
Learning notes for the migrations feature in the Django framework (3)
[Django Rest Framework] Customize the filter function using Django-Filter
Learning notes for the migrations feature in the Django framework (1)
Django python web framework
Creating an API that returns negative-positive inference results using BERT in the Django REST framework
Model changes in Django
Framework development in Python
How to reset password via API using Django rest framework
Django rest framework decorators ʻaction decorator replaces list_route and detail_route`