Opened 16 years ago
Closed 16 years ago
#8005 closed (duplicate)
Make it easier to alter a model saved by the admin (e.g. add the user that created or updated it)
Reported by: | simon | Owned by: | nobody |
---|---|---|---|
Component: | contrib.admin | Version: | dev |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Design decision needed | |
Has patch: | yes | Needs documentation: | yes |
Needs tests: | yes | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
A very common requirement for customising the admin is to automatically update a created_by or updated_by field with the user object that made changes to an object. This is currently way harder than it should be: http://www.djangosnippets.org/snippets/903/
I propose adding an extra subclassable method that makes it trivial to intercept the model as it is being created and perform additional work on it. Here's an example (incomplete) patch illustrating the idea: http://code.djangoproject.com/attachment/ticket/8005/8005.1.diff
This would allow ModelAdmin subclasses to make additional changes to the model by calling form.save(commit=False) instead. For the admin user described above, the subclass would look like this:
class ArticleAdmin(admin.ModelAdmin): def save_model_add(self, request, form, formsets): new_object = form.save(commit=False) new_object.created_by = request.user new_object.updated_by = request.user new_object.save() if formsets: for formset in formsets: formset.instance = new_object formset.save() return new_object def save_model_change(self, request, form, formsets): new_object = form.save(commit=False) new_object.updated_by = request.user new_object.save() if formsets: for formset in formsets: formset.save() return new_object
This is a big improvement, although I'm not too happy with the need to duplicate the formset logic. Maybe that should be split out in to a separate over-ridable method as well.
Attachments (3)
Change History (11)
by , 16 years ago
Attachment: | 8005.1.diff added |
---|
comment:1 by , 16 years ago
Description: | modified (diff) |
---|
by , 16 years ago
Attachment: | 8005.2.diff added |
---|
comment:2 by , 16 years ago
http://code.djangoproject.com/attachment/ticket/8005/8005.2.diff is a bit better - it lets you skip the formset boilerplate, so now the subclass looks like this:
class ArticleAdmin(admin.ModelAdmin): def save_model_add(self, request, form, formsets): new_object = form.save(commit=False) new_object.created_by = request.user new_object.updated_by = request.user new_object.save() return new_object def save_model_change(self, request, form, formsets): new_object = form.save(commit=False) new_object.updated_by = request.user new_object.save() return new_object
by , 16 years ago
Attachment: | 8005.3.diff added |
---|
Patch illustrating different approach, using pre_save and post_save hooks
comment:3 by , 16 years ago
I've added a third option, based on feedback from Julien Phalip: http://code.djangoproject.com/attachment/ticket/8005/8005.2.diff
Now the subclass looks like this:
class ArticleAdmin(admin.ModelAdmin): def pre_save(self, request, instance, is_add): if is_add: instance.created_by = request.user instance.updated_by = request.user
Mailing list thread is here: http://groups.google.com/group/django-developers/browse_thread/thread/620b4dffa8a7f58f
comment:4 by , 16 years ago
Previous comment linked to the wrong patch; should have linked to http://code.djangoproject.com/attachment/ticket/8005/8005.3.diff
comment:5 by , 16 years ago
I really think the pre_save
and post_save
hooks are the best approach here. Another example of what you could do with it:
class ArticleAdmin(admin.ModelAdmin): def post_save(self, request, instance, is_add): if is_add: mail_admins("New article created", "A new article created by %s in the admin. Check it out: %s" % (instance.created_by, instance.get_absolute_url()) )
comment:6 by , 16 years ago
Some other approaches have been proposed in #6406. Not sure which ticket should be considered most in this regard.
comment:7 by , 16 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
comment:8 by , 16 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Improved patch; refactored formset boilerplate in to a separate method