Skip to content

Instantly share code, notes, and snippets.

@jacobwegner
Last active January 30, 2024 06:29
Show Gist options
  • Save jacobwegner/3c0794ba49c8332a3221ca5088b0f357 to your computer and use it in GitHub Desktop.
Save jacobwegner/3c0794ba49c8332a3221ca5088b0f357 to your computer and use it in GitHub Desktop.
Recovering data deleted via the Django admin

I was looking for a way to revert data deleted by mistake from the Django admin.

I reverse-engineered how Django's admin builds the list of objects displayed on the "Are you sure?" confirmation page.

Given a single obj or list of objs, the script included in this gist will:

  • Use the NestedObjects utility to determine the objects that would be deleted
  • Pass those objects to Django's JSON serializer
  • Write the objects to adeleted-objects fixture

This allowed me to:

  • Restore a database locally to a time before the object was deleted
  • Generate the fixture
  • Apply the fixture to the database to restore data
from django.core import serializers
from django.contrib.admin.utils import NestedObjects
from django.db import models, transaction, router
# assuming `obj` is the model instance for deletion:
objs = [obj]
using = router.db_for_write(obj._meta.model)
collector = NestedObjects(using=using)
collector.collect(objs)
def get_objects_callback():
for qs in collector.data.values():
for obj in qs:
yield obj
output_format = "json"
with open("deleted-objects.json", "w") as f:
serializers.serialize(output_format, get_objects_callback(), indent=2,
use_natural_foreign_keys=True,
use_natural_primary_keys=True,
stream=f)
@jacobwegner
Copy link
Author

@i-salameh95: I would recommend testing this in a local or staging environment first.

The steps would be to:

  • Restore a database backup that has the deleted object(s)
  • Use the script above to generate the deleted-objects.json fixture
  • Then, restore a backup / snapshot of the current production data in your local / staging environment
  • Use loaddata to load the fixture in your local / staging environment
  • Verify that the objects are restored in your local / staging environment
  • Finally, Use loaddata to load the fixture in your production environment

The point of this Gist is to avoid restoring a backup into the production environment to "recover" the deleted objects.

@jacobwegner
Copy link
Author

@i-salameh95 I'm really glad you left a comment...I had a need for this Gist again this week and probably wouldn't have remembered that I had wrote it without getting your comment notification.

The Gist still works...I may try and update it or even re-package it into a more full-featured library down the road.

Best,

@i-salameh95
Copy link

Glad that I could help you remember !
Thanks for replying, and clarifying that it works. I have the trust now to try it on live.

@bhaumikb
Copy link

I also tested this script and it is 100% working.
Thanks a lot, @jacobwegner for making this script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment