Skip to content

Commit

Permalink
[1.0.X] Fixed #10899 -- Ensured that log messages for deletions in th…
Browse files Browse the repository at this point in the history
…e admin contain useful descriptions. Thanks to Jeremy Dunck for the patch.

Merge of r10686 from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@10720 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
freakboy3742 committed May 8, 2009
1 parent 41ba8e7 commit 8397c1f
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 42 deletions.
82 changes: 41 additions & 41 deletions django/contrib/admin/options.py
Expand Up @@ -46,7 +46,7 @@ def formfield_for_dbfield(self, db_field, **kwargs):
If kwargs are given, they're passed to the form Field's constructor.
"""

# If the field specifies choices, we don't need to look for special
# admin widgets - we just need to use a select widget of some kind.
if db_field.choices:
Expand Down Expand Up @@ -79,17 +79,17 @@ def formfield_for_dbfield(self, db_field, **kwargs):
if isinstance(db_field, models.TimeField):
kwargs['widget'] = widgets.AdminTimeWidget
return db_field.formfield(**kwargs)

# For TextFields, add a custom CSS class.
if isinstance(db_field, models.TextField):
kwargs['widget'] = widgets.AdminTextareaWidget
return db_field.formfield(**kwargs)

# For URLFields, add a custom CSS class.
if isinstance(db_field, models.URLField):
kwargs['widget'] = widgets.AdminURLFieldWidget
return db_field.formfield(**kwargs)

# For IntegerFields, add a custom CSS class.
if isinstance(db_field, models.IntegerField):
kwargs['widget'] = widgets.AdminIntegerFieldWidget
Expand All @@ -104,7 +104,7 @@ def formfield_for_dbfield(self, db_field, **kwargs):
if isinstance(db_field, models.CharField):
kwargs['widget'] = widgets.AdminTextInputWidget
return db_field.formfield(**kwargs)

# For FileFields and ImageFields add a link to the current file.
if isinstance(db_field, models.ImageField) or isinstance(db_field, models.FileField):
kwargs['widget'] = widgets.AdminFileWidget
Expand Down Expand Up @@ -281,56 +281,56 @@ def get_form(self, request, obj=None, **kwargs):
def get_formsets(self, request, obj=None):
for inline in self.inline_instances:
yield inline.get_formset(request, obj)

def log_addition(self, request, object):
"""
Log that an object has been successfully added.
Log that an object has been successfully added.
The default implementation creates an admin LogEntry object.
"""
from django.contrib.admin.models import LogEntry, ADDITION
LogEntry.objects.log_action(
user_id = request.user.pk,
user_id = request.user.pk,
content_type_id = ContentType.objects.get_for_model(object).pk,
object_id = object.pk,
object_repr = force_unicode(object),
object_repr = force_unicode(object),
action_flag = ADDITION
)

def log_change(self, request, object, message):
"""
Log that an object has been successfully changed.
Log that an object has been successfully changed.
The default implementation creates an admin LogEntry object.
"""
from django.contrib.admin.models import LogEntry, CHANGE
LogEntry.objects.log_action(
user_id = request.user.pk,
content_type_id = ContentType.objects.get_for_model(object).pk,
object_id = object.pk,
object_repr = force_unicode(object),
action_flag = CHANGE,
user_id = request.user.pk,
content_type_id = ContentType.objects.get_for_model(object).pk,
object_id = object.pk,
object_repr = force_unicode(object),
action_flag = CHANGE,
change_message = message
)

def log_deletion(self, request, object, object_repr):
"""
Log that an object has been successfully deleted. Note that since the
object is deleted, it might no longer be safe to call *any* methods
on the object, hence this method getting object_repr.
The default implementation creates an admin LogEntry object.
"""
from django.contrib.admin.models import LogEntry, DELETION
LogEntry.objects.log_action(
user_id = request.user.id,
content_type_id = ContentType.objects.get_for_model(self.model).pk,
object_id = object.pk,
user_id = request.user.id,
content_type_id = ContentType.objects.get_for_model(self.model).pk,
object_id = object.pk,
object_repr = object_repr,
action_flag = DELETION
)


def construct_change_message(self, request, form, formsets):
"""
Construct a change message from a changed object.
Expand All @@ -356,10 +356,10 @@ def construct_change_message(self, request, form, formsets):
'object': force_unicode(deleted_object)})
change_message = ' '.join(change_message)
return change_message or _('No fields changed.')

def message_user(self, request, message):
"""
Send a message to the user. The default implementation
Send a message to the user. The default implementation
posts a message using the auth Message object.
"""
request.user.message_set.create(message=message)
Expand All @@ -370,7 +370,7 @@ def save_form(self, request, form, change):
the object is being changed, and False if it's being added.
"""
return form.save(commit=False)

def save_model(self, request, obj, form, change):
"""
Given a model instance save it to the database.
Expand Down Expand Up @@ -408,14 +408,14 @@ def render_change_form(self, request, context, add=False, change=False, form_url
"admin/%s/change_form.html" % app_label,
"admin/change_form.html"
], context, context_instance=template.RequestContext(request))

def response_add(self, request, obj, post_url_continue='../%s/'):
"""
Determines the HttpResponse for the add_view stage.
"""
opts = obj._meta
pk_value = obj._get_pk_val()

msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj)}
# Here, we distinguish between different save types by checking for
# the presence of keys in request.POST.
Expand All @@ -424,7 +424,7 @@ def response_add(self, request, obj, post_url_continue='../%s/'):
if request.POST.has_key("_popup"):
post_url_continue += "?_popup=1"
return HttpResponseRedirect(post_url_continue % pk_value)

if request.POST.has_key("_popup"):
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
# escape() calls force_unicode.
Expand All @@ -443,14 +443,14 @@ def response_add(self, request, obj, post_url_continue='../%s/'):
else:
post_url = '../../../'
return HttpResponseRedirect(post_url)

def response_change(self, request, obj):
"""
Determines the HttpResponse for the change_view stage.
"""
opts = obj._meta
pk_value = obj._get_pk_val()

msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj)}
if request.POST.has_key("_continue"):
self.message_user(request, msg + ' ' + _("You may edit it again below."))
Expand Down Expand Up @@ -503,7 +503,7 @@ def add_view(self, request, form_url='', extra_context=None):
form.save_m2m()
for formset in formsets:
self.save_formset(request, form, formset, change=False)

self.log_addition(request, new_object)
return self.response_add(request, new_object)
else:
Expand Down Expand Up @@ -599,11 +599,11 @@ def change_view(self, request, object_id, extra_context=None):
form.save_m2m()
for formset in formsets:
self.save_formset(request, form, formset, change=True)

change_message = self.construct_change_message(request, form, formsets)
self.log_change(request, new_object, change_message)
return self.response_change(request, new_object)

else:
form = ModelForm(instance=obj)
prefixes = {}
Expand All @@ -624,7 +624,7 @@ def change_view(self, request, object_id, extra_context=None):
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets)
inline_admin_formsets.append(inline_admin_formset)
media = media + inline_admin_formset.media

context = {
'title': _('Change %s') % force_unicode(opts.verbose_name),
'adminform': adminForm,
Expand Down Expand Up @@ -705,11 +705,11 @@ def delete_view(self, request, object_id, extra_context=None):
if perms_needed:
raise PermissionDenied
obj_display = force_unicode(obj)
obj.delete()

self.log_deletion(request, obj, obj_display)
obj.delete()

self.message_user(request, _('The %(name)s "%(obj)s" was deleted successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj_display)})

if not self.has_change_permission(request, None):
return HttpResponseRedirect("../../../../")
return HttpResponseRedirect("../../")
Expand Down Expand Up @@ -784,7 +784,7 @@ def __init__(self, parent_model, admin_site):
self.verbose_name = self.model._meta.verbose_name
if self.verbose_name_plural is None:
self.verbose_name_plural = self.model._meta.verbose_name_plural

def _media(self):
from django.conf import settings
js = []
Expand Down
5 changes: 4 additions & 1 deletion tests/regressiontests/admin_views/tests.py
Expand Up @@ -6,7 +6,7 @@
from django.test import TestCase
from django.contrib.auth.models import User, Permission
from django.contrib.contenttypes.models import ContentType
from django.contrib.admin.models import LogEntry
from django.contrib.admin.models import LogEntry, DELETION
from django.contrib.admin.sites import LOGIN_FORM_KEY
from django.contrib.admin.util import quote
from django.utils.html import escape
Expand Down Expand Up @@ -557,6 +557,9 @@ def testDeleteView(self):
post = self.client.post('/test_admin/admin/admin_views/article/1/delete/', delete_dict)
self.assertRedirects(post, '/test_admin/admin/')
self.failUnlessEqual(Article.objects.all().count(), 2)
article_ct = ContentType.objects.get_for_model(Article)
logged = LogEntry.objects.get(content_type=article_ct, action_flag=DELETION)
self.failUnlessEqual(logged.object_id, u'1')
self.client.get('/test_admin/admin/logout/')

class AdminViewStringPrimaryKeyTest(TestCase):
Expand Down

0 comments on commit 8397c1f

Please sign in to comment.