On Wed, Aug 12, 2009 at 9:24 AM, David<da...@davidfindlay.org> wrote: > > After being unable to get any advice or further information via > google, #django or the users' mailing list, I opened > http://code.djangoproject.com/ticket/11652 regarding the admin > interface not preventing simultaneous editing of the same record (or > at least not providing that as an option). I guess this is not a > typical usage scenario, but for my use case I would like to implement > it if at all possible.
You are correct that django.contrib.admin doesn't currently provide protection against simultaneous edits. I can't say this is a problem I've experienced myself. The sites I've dealt with have fairly low traffic admin sites, or only a small number of editors. However, I agree that it would be nice if this sort of protection were to be 'baked in' - preferably at the ModelForm level, if that's not possible, then as a specific extension to admin. > My first thought was to try grab a JSON representation of the original > record in an override of ModelAdmin.change_view; I thought I might be > able to save this via extra_context and somehow get it back when > change_view is called the second time for the HTTP POST of the > modified record. I was hoping to then compare that saved JSON > representation of the original record with the JSON representation of > the record as it exists in the database on that POST call; if they > differed then someone must have changed the record in the meantime and > so I could generate an error message. > > I realized if I added an AutoField data to the record and saved that > instead, then that would be a lot cheaper to save and compare, but I > still don't know how to save that information. There are any number of ways to solve this problem by adding a field to the model (autofield with an 'edit number', timestamp tracking last edit time etc). However, these aren't really candidates for a general solution. > Is there a way to save information in the session and get it back on > subsequent calls? Well... yes... that's what a session is :-) That said, I'm not sure the session is the right place for this. It really needs to be stored per form - consider the case of a single user with multiple tabs open in the admin interface. > Using an AutoField date it would probably be sufficient to just know > when the original GET of the record happened for the user to start > changing it. Is there a way to find that out? > > If anyone has any pointers or advice I'd be most grateful. A few random thoughts: Django's forms already have some functionality that is tangentially related. If you have fields with callable default values, Django will insert a hidden field into the form to contain the initial value. This is required because the value of the callable at time of POST processing may not be the same as the value of the callable when the form is originally displayed. This isn't exactly the same scenario, but it may give you some ideas to see how this could be implemented for the larger problem. Another piece of related work - In the run up to v1.1, a few changes were made to avoid modification issues in FormSets. #10922 described a problem - again, it's not quite the same problem, but it's vaguely related, and may provide some illumination on ways to tackle the problem. A related thought - prior to v1.0, Django's login form would store POST data in a pickle in a hidden field if the login session data expired. This was removed from the login form because an attack vector was demonstrated using this POST data, but as a general approach for checking for modifications, I suspect it could be used here. A hidden field on a form that contains a pickle of the original object data could be added to the field on the original form render; on POST, the pickle could be decompiled to give the original field values for comparison. A somewhat simpler approach would be to use a checksum - calculate an md5/sha hash of the original object data and include it in a hidden field. On submit, recompute the hash based on current values. If the has changed, there have been modifications. I suspect that this would be easier to implement, but would give you slightly less feedback - it would be able to tell you that the object has been modified, but wouldn't be able to tell you the nature of the modifications. Yet another approach would be to only make this 'feature' available to those objects that support it. That is, define a 'ConcurrentModificationField' as an extension of AutoField that you can put on a model; this field would include a default form implementation that does the appropriate validation. This isn't a complete solution, but it could be implemented without any modifications to Django itself. If this is a problem that interests you, then I encourage you to dig around. Developing the code to implement this fix will certainly give you a very good grounding in the internals of Django's form infrastructure. If you can find a clean way to implement this functionality, then we are certainly interested in integrating this into the Django core. Yours, Russ Magee %-) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---