makinacorpus / django-safedelete

Mask your objects instead of deleting them from your database.
https://django-safedelete.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
677 stars 122 forks source link

Version of dumpdata that includes soft deleted models #198

Open danizen opened 2 years ago

danizen commented 2 years ago

We had a situation arise with an application written in 2017 using a home-grown ModelManager which works similarly to the SafeDeleteManager. Because we are migrating from one database to another, and there is not too much data, we attempted to use the management commands dumpdata and loaddata to copy the data to the new database instance.

This caused referential integrity errors because dumpdata did not include the deleted models. My suggestion is that safedelete includes its own dumpdata command which avoids the problem:

from types import MethodType
from django.apps import apps
from django.db import models
from django.core.management.commands.dumpdata import Command as BaseCommand

# not quite using django-safedelete, but other apps here do
from lrmaint.models import SoftDeleteManager

class Command(BaseCommand):

    def handle(self, *app_labels, **options):
        print('This is a wrapper around Django default dumpdata')

        # patch each softdeletemanager to avoid overload
        for model in apps.get_app_config('lrmaint').get_models():
            if isinstance(model.objects, SoftDeleteManager):
                model.objects.get_queryset = MethodType(models.Manager.get_queryset, model.objects)

        # defer to dumpdata
        super().handle(*app_labels, **options)
danizen commented 2 years ago

Another way to mitigate this would be to mention it in the documentation as a warning.

danizen commented 2 years ago

The actual result was that dump worked, but load failed with a referential integrity error.

Gagaro commented 2 years ago

Thanks for the report :+1: . Feel free to open a PR implementing this.

yourcelf commented 2 years ago

This can be done using the built-in dumpdata by passing the -a/--all flag:

./manage.py dumpdata --all myapp

That causes dumpdata to use the base manager rather than the default manager, and results in safe-deleted objects being included in the dump.