Logging the user that deleted an object

1,559 views
Skip to first unread message

alas...@thenicols.net

unread,
Sep 13, 2013, 11:02:55 AM9/13/13
to django-r...@googlegroups.com
Hi,

We are using django-reversion to log which user made changes to an object.

It works great for logging changes, but I haven't managed to work out which user deleted an object. I believe that is because the last version stored in the database is from when the object was last edited, not when it was finally deleted.  

I have thought of a couple of approaches to solve the problem:

1. When deleting the object, first call save() and set a comment to say the object was deleted. Then call delete.

    with reversion.revision():
        obj.save()
        reversion.set_comment("Deleted by user")
        obj.delete()

2. Add a deleted flag to my model, then set deleted=True and save instead of 

    with reversion.revision():
        obj.deleted = True,
        obj.save()

This requires changing all my filters to exclude 'deleted' objects/

Are there any other approaches that I haven't thought of?

Cheers,
Alasdair

Dave Hall

unread,
Sep 14, 2013, 1:14:22 AM9/14/13
to django-r...@googlegroups.com

A while ago, I allowed myself to be persuaded into adding an added/changed/deleted flag to the Version model, which has proven to be the worst idea ever, and is scheduled for removal in an upcoming release.

So its best to ignore that aspect of django-reversion.

The way it's supposed to work, and will continue to work forever, is analogous to Git scm, in that a Revision consists of a consistent snapshot of a group of related models (or just one model). If you delete a model, then django-reversion knows that it's been deleted because its PK is in the version table, but not in the "live" table. There is no record for "x has been deleted" (well, there is, but that was the "worst idea ever" feature mentioned above, and it will be removed very soon).

So, finding out who deleted a model is tricky. Your solution 1 is a good approach, and will continue to work for future releases of django-reversion. So use that!

--
You received this message because you are subscribed to the Google Groups "django-reversion discussion group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-reversi...@googlegroups.com.
To post to this group, send an email to django-r...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-reversion.
For more options, visit https://groups.google.com/groups/opt_out.

g

unread,
Sep 14, 2013, 8:13:49 AM9/14/13
to django-r...@googlegroups.com

There is no record for "x has been deleted" (well, there is, but that was the "worst idea ever" feature mentioned above, and it will be removed very soon).


1. When deleting the object, first call save() and set a comment to say the object was deleted. Then call delete.

    with reversion.revision():
        obj.save()
        reversion.set_comment("Deleted by user")
        obj.delete()



I am new to the list so I apologize for not being fully aware of the history behind why it is "the worst idea ever".  I've tried to catch up on why it is a bad idea.

However, the "deleted" record seems particularly useful, but probably not for statistics as mentioned in issue #164.  I see it being very useful for being able to find all records deleted by a specific user, most likely filtered on a specific day or something like that.  This makes it easy to undo malicious/accidental deletion after the fact.  I deal with very non-technical users, so maybe this is an edge case.  I have encountered people deleting records accidentally but not knowing what they deleted so they weren't any help when I had to restore the deleted data.  I've also had users maliciously delete data and they were obviously not helpful in the recovery.

Are there any cases where it wouldn't be beneficial to snapshot the instance on delete as a final precaution to record the user and time of deletion?  It seems like the snippet above should be incorporated into a post_delete signal for any reversion registered model.  This is actually my main use case and why I looked for a project like django-reversion.
 

Dave Hall

unread,
Sep 15, 2013, 11:38:55 AM9/15/13
to django-r...@googlegroups.com

It's a valid use-case, I realise.

The thin to remember about django-reversion is that it's about point-in-time recovery, which is different to an undo feature.

With an undo feature, you would find the "action" that caused the deletions, and undo it.

With point-in-time recovery, you would recover the model from a time where it wasn't deleted.

In its purest form, django-reversion wouldn't store comments or user models associated with a revision at all. This was only done to make the admin integration much simpler.

With a typical version control system, you'd snapshot the entire state of the project in the form of a diff, or a complete snapshot, at which point a deletion is represented as a negative diff for the contents of a file.

When version controlling data in a database, snapshotting the entire database for each revision isn't feasible for anything other than toy databases. If you treat each table as a standalone entity, then recording deletions becomes possible.

However, when a revision contains a group of models from different tables, the situation becomes vastly more complicated. At this point a revision can be sent to represent the state of a collection of related models at a point in time. If a snapshot is saved again at a later date, then you can tell if a model has been deleted because it will be absent from the later revision.

In your case, I would listen to the delete signal for your models, and log these deletions against the initiating user. Then in the event of a large-scale deletion, you can look at what was deleted, and recover it.

In this way, you separate the "audit trail" and "snapshotting/recovery" features into two separate concerns, which is probably how django-reversion should have been written in the first place.

--

g

unread,
Sep 16, 2013, 11:24:38 AM9/16/13
to django-r...@googlegroups.com

In its purest form, django-reversion wouldn't store comments or user models associated with a revision at all. This was only done to make the admin integration much simpler.




I think the storing the user and a comment in some form or fashion is a good idea.  All popular version control systems I have used do this.  But I understand what you mean.




In your case, I would listen to the delete signal for your models, and log these deletions against the initiating user. Then in the event of a large-scale deletion, you can look at what was deleted, and recover it.

In this way, you separate the "audit trail" and "snapshotting/recovery" features into two separate concerns, which is probably how django-reversion should have been written in the first place.



Sounds like a good implementation strategy.  Thanks 

Arthur Pemberton

unread,
Oct 10, 2013, 9:35:40 AM10/10/13
to django-r...@googlegroups.com


On Sunday, September 15, 2013 11:38:55 AM UTC-4, Dave Hall wrote:

It's a valid use-case, I realise.

The thin to remember about django-reversion is that it's about point-in-time recovery, which is different to an undo feature.

I am curious as to why you've deemed maintaining information on who (user_id) and what (added/changed/deleted) to be a bad idea. I'm sure you have your reasons, but those bits of information seem very useful. I'm thinking of similiar implements like MS Sharepoint which can maintain a history of changes to a "list".

Arthur

Dave Hall

unread,
Oct 10, 2013, 12:26:00 PM10/10/13
to django-r...@googlegroups.com
Simply put, some projects don't use django.contrib.auth. By making the user field part of the Revision model, it's required to install django.contrib.auth even if it's never going to be used in your project.

django-reversion has a more generic way of attaching meta information to a revision. In retrospect, using that would have been a good decision. However, it's most likely too late to make that sort of change now!


--

Arthur Pemberton

unread,
Oct 10, 2013, 4:14:29 PM10/10/13
to django-r...@googlegroups.com


On Thursday, October 10, 2013 12:26:00 PM UTC-4, Dave Hall wrote:
Simply put, some projects don't use django.contrib.auth. By making the user field part of the Revision model, it's required to install django.contrib.auth even if it's never going to be used in your project.

django-reversion has a more generic way of attaching meta information to a revision. In retrospect, using that would have been a good decision. However, it's most likely too late to make that sort of change now!


Would using contenttype break that strong dependence?

g

unread,
Oct 10, 2013, 4:22:18 PM10/10/13
to django-r...@googlegroups.com
 
Would using contenttype break that strong dependence?
 
 
 
I think generic relationships aren't meant for this use case because it would only ever point to one model.
 
You could conditionally define the relationship field instead of using a generic relationship.
 
This would be backwards compatible and allow users not to use contrib.auth if that is important.  Though I don't know how common this requirement would be.  And then you have to add checks to see if the field exists or not.

g

unread,
Oct 10, 2013, 4:27:00 PM10/10/13
to django-r...@googlegroups.com
Although I have a hard time understanding a use for reversions without contrib.auth.   If you don't use contrib.auth, how do you control who has permission to revert revisions?
 
An anonymous only wiki perhaps?  But that would still need an administrator I would imagine.

Dave Hall

unread,
Oct 11, 2013, 3:28:05 AM10/11/13
to django-r...@googlegroups.com
The point is that the user and comment fields on Revision could be implemented using the custom metadata feature of django-reversion.


It's probably too late to make this sort of change to the codebase now, but the advantages would be removing a dependency on django.contrib.auth, and the only disadvantage would be another database model being used in the typical admin-centric setup.


On 10 October 2013 21:27, g <wgor...@gmail.com> wrote:
Although I have a hard time understanding a use for reversions without contrib.auth.   If you don't use contrib.auth, how do you control who has permission to revert revisions?
 
An anonymous only wiki perhaps?  But that would still need an administrator I would imagine.

--

leandri...@gmail.com

unread,
Jun 16, 2016, 11:15:00 AM6/16/16
to django-reversion discussion group, alas...@thenicols.net
how to get deleted list of some model. Table id is serial pk and never have more than one version of same model and i need to get list of all deleted objects and user, date of objects are deleted i tried this deleted_list = reversion.get_deleted (Model) and in this dont get user and date when are deleted excusme my english :( Trato de escribir lo mejor que puedo

Dave Hall

unread,
Jun 16, 2016, 11:45:34 AM6/16/16
to django-reversion discussion group, alas...@thenicols.net
The user who deleted a model isn't logged in the version data, as reversion takes no action when a model is deleted.

If you want this information, you'll need to keep a small table of audit information up to date using the pre_delete model signal.

On Thu, 16 Jun 2016 at 16:15 <leandri...@gmail.com> wrote:
how to get deleted list of some model. Table id is serial pk and never have more than one version of same model and i need to get list of all deleted objects and user, date of objects are deleted i tried this deleted_list = reversion.get_deleted (Model) and in this dont get user and date when are deleted excusme my english :( Trato de escribir lo mejor que puedo

--
You received this message because you are subscribed to the Google Groups "django-reversion discussion group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-reversi...@googlegroups.com.
To post to this group, send email to django-r...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-reversion.
For more options, visit https://groups.google.com/d/optout.

691671947

unread,
Jun 16, 2016, 2:00:24 PM6/16/16
to django-r...@googlegroups.com
ok thanks 

I'm looking for ways 

--
You received this message because you are subscribed to a topic in the Google Groups "django-reversion discussion group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-reversion/SB953FlKoSc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-reversi...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages