Search code examples
djangodjango-rest-frameworkdjango-simple-history

How to add a Reason for Deletion to all DRF Delete APIs


In a Django Rest Framework app using Django Simple History to track model changes, how would one force a user to pass a Reason for Deletion for all Destroy End Points and then pass that reason to Django Simple History's Change Reason?

Also, for related models with a Delete Cascade, would that reason be passed on to the related deleted entries?

Update:

Tried overriding the destroy method as below following another question here on SO. Issue is, where is the changeReason i.e. history_change_reason located after the delete? I thought it would be a column in the historical table? However, its not there so even if the code below is working, I can't find where the reason has been saved.

class DeleteViewSet(mixins.DestroyModelMixin):
    def destroy(self, request, *args, **kwargs):
        try:
            if 'delete_reason' not in request.data.keys():
                return Response(status=status.HTTP_400_BAD_REQUEST,data='{delete_reason: Invalid Delete Reason}')
            else:
                instance = self.get_object()
                instance.changeReason = request.data['delete_reason']
                instance.save()
                self.perform_destroy(instance)
        except Http404:
            pass
        return Response(status=status.HTTP_204_NO_CONTENT)

Missing History Change Reason Column:

The only history_* I see in all history tables are:

1. history_id
2. history_date
3. history_type
4. history_user_id

I can't find history_change_reason in any of the history tables


Solution

  • Ok. Found the answer to two of my problems.

    Missing History Change Reason Column:

    This was a version issue. pip3.6 install --upgrade django-simple-history and then migrate solved this.

    Deletion Reason as a Mixin:

    This works by checking if deletion_reason is provided.

    class DeleteViewSet(mixins.DestroyModelMixin):
        def destroy(self, request, *args, **kwargs):
            try:
                if 'delete_reason' not in request.data.keys():
                    return Response(status=status.HTTP_400_BAD_REQUEST,data='{delete_reason: Invalid Delete Reason}')
                else:
                    instance = self.get_object()
                    instance.changeReason = request.data['delete_reason']
                    # instance.save()  ==>Don't do this because it will cause a second instance to be saved in the history tables
                    self.perform_destroy(instance)
            except Http404:
                pass
            return Response(status=status.HTTP_204_NO_CONTENT)
    

    Not solved:

    Passing the deletion_reason to all tables that are subsequently deleted when you have a delete_cascade in the relation between models.