8

We have django-simple-history set up for our models. Recently a whole bunch of models were mysteriously deleted. This was noticed a few days after the fact, so it would be nice to avoid a full DB backup restore since that would wipe manual changes that happened after the fact.

I cannot find any way to easily restore an model instance, specifically a deleted one. I can query the Historical version of the model and find everything that was deleted. With that I can also observe that all of them had deletions as their last change. I can use the instance property on history - 1 to get the state before deletion but if I try to save that it errors since the model instance was deleted and doesn't exist anymore.

So basically, what is the cleanest way to restore a deleted model instance if I have the Historical record of it with django-simple-history? I would like to retain the history if possible, so I am looking into any solution before totally recreating the objects.

Dhia
  • 10,119
  • 11
  • 58
  • 69
zaknotzach
  • 977
  • 1
  • 9
  • 18

4 Answers4

3

As I understand, the question, it is about restoring a deleted model instance, not the class itself. So Kal's answer does not help here. To restore a deleted instance, simple history can NOT be used. According to the documentation, simple history can only restore model instances that are still existing. Since you have a full backup of the database, you can import this database into the django environment, load the old model instance from this backup database and save it to the production database (choose the database in django shell with "using"). See this post. The best way to avoid such situations is to use the app "reversion". With this django-app, you actually can restore deleted instances. See the documentation.

user3061675
  • 161
  • 1
  • 4
2

If model using django-simple-history then,

Data can be restored from the historical model.

We need to filter from the historical model. for eg with some keyword or in some date range in which period the data got deleted accidentally.

For eg. the Model Name is Car, then by default django-simple-history creates a historical model as HistoricalCar.

historical_data = HistoricalCar.objects.filter(history_type='-')
for each in historical_data:
   instance = each.instance  # This return instance of car.
   instance.pk = None  # Create New Instance
   instance.save()

Furkan Siddiqui
  • 1,725
  • 12
  • 19
  • 1
    any reason to use `instance.pk = None`, I did some tests without this line, and I could revert the deleted object keeping the old id (which is good case it has other relations) – Guilherme Mar 29 '23 at 19:22
  • Thanks For finding @Guilherme, you are correct reverting with old id is good case `instance.pk=None` will create new id. – Furkan Siddiqui Mar 30 '23 at 04:52
0

Do you mean that your model, not just the instances, has been completely deleted? If that’s the case, it probably means some migration removed it.

You could try reverting the migration then restore from the Historical record.

Kal
  • 1,707
  • 15
  • 29
0

The previous version of your model is stored in the _HISTORICAL<model_name> table. You could do a simple sql insert/select query to copy the data from that table back into the original table. Something like the below would work, but check the correct sql syntax for your database.

insert into app_mymodel (col_a, col_b) 
select col_a, col_b from app_HISTORICALmymodel 
where id in (1,2,3...)
Lingster
  • 977
  • 10
  • 21