If you are running a Django application, hopefully you have regular backups of the DB. We had a customer who realized they deleted something over a month ago and needed the deleted objects restored. Instead of just reverting the entire DB and losing all of the new information, I wrote a simple script that will create a fixture of everything that was deleted that can then be used with loaddata.
Thanks goes to Constantin Berzan for how to programmatically enumerate objects that will get cascade-deleteded in Django.
Step By Step
- In a local development environment restore the DB to the version with the objects you need to restore into production.
- Run python manage.py shell
- In the shell type execfile('dump_partial.py') where ‘dump_partial.py’ is what you named your customized version of the script below.
- On the production environment, place the dump.json file generated in step 3 in the same directory as manage.py and run python manage.py loaddata dump.json
dump_partial.py
Save this file in the same directory as your Django manage.py on your local development environment. Update what you need to dump as needed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
from APP.models import MODELNAME # Update Me to include the models from your Django app that you need to restore from django.contrib.admin.util import NestedObjects from django.db import DEFAULT_DB_ALIAS from django.core import serializers restore_me = MODEL.objects.filter(id=ID_OF_OBJECT_TO_RESTORE) # Update to get the item that was deleted. collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect(restore_me) # This generates a hierarchical list of all of the objects related to the object that was deleted. # The same output that Django creates when it prompts you for confirmation to delete something. result = collector.nested() output = '[' # Start the json string. def json_dump(obj): global output # I cringe when I write this, but for the sake of what this script is doing simple is fine. for model in obj: if not isinstance(model, list): # Ignore many to many tables as they are included in the primary object serialization if "_" not in model.__class__.__name__: # Use Django's built in serializer, and strip off the array brackets output += serializers.serialize("json", [model])[1:-1] # append a comma output += "," else: json_dump(model) # Yay for recursion json_dump(result) output = output[:-1] + "]" # remove the last comma and add the ending array bracket. with open("dump.json", "w+") as dump: # dump it to a file dump.write(output) |
Latest posts by Travis Payton (see all)
- Adventures with Sendmail - January 3, 2019
- Django – selective restore of DB dump - April 11, 2016
- Cord Cutting The Geek Way – Watch your favorite TV shows for free, anytime, anywhere! - January 20, 2016
1 comment for “Django – selective restore of DB dump”