-
Notifications
You must be signed in to change notification settings - Fork 122
/
admin.py
160 lines (138 loc) · 5.23 KB
/
admin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import django
from django.contrib import admin, messages
from django.contrib.admin import helpers
from django.contrib.admin.models import LogEntry, CHANGE
try:
# Django 1.7
from django.contrib.admin.utils import model_ngettext
except ImportError:
# Django < 1.7
from django.contrib.admin.util import model_ngettext
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
try:
# Django >= 1.3
from django.template.response import TemplateResponse
except ImportError:
from django.shortcuts import render_to_response
from django.template import RequestContext
try:
# Django > 1.3
from django.utils.encoding import force_text
except ImportError:
# Django 1.3
from django.utils.encoding import force_unicode as force_text
from django.utils.translation import ugettext_lazy as _
def highlight_deleted(obj):
"""
Display in red lines when object is deleted.
"""
if not getattr(obj, 'deleted', False):
return obj
else:
return '<span class="deleted">{0}</span>'.format(obj)
highlight_deleted.short_description = _("Name")
highlight_deleted.allow_tags = True
class SafeDeleteAdmin(admin.ModelAdmin):
"""
An abstract ModelAdmin which will include deleted objects in its listing.
:Example:
>>> from safedelete.admin import SafeDeleteAdmin, highlight_deleted
>>> class ContactAdmin(SafeDeleteAdmin):
... list_display = (highlight_deleted, "first_name", "last_name", "email") + SafeDeleteAdmin.list_display
... list_filter = ("last_name") + SafeDeleteAdmin.list_filter
"""
undelete_selected_confirmation_template = "safedelete/undelete_selected_confirmation.html"
list_display = ('deleted',)
list_filter = ('deleted',)
exclude = ('deleted',)
actions = ('undelete_selected',)
class Meta:
abstract = True
class Media:
css = {
'all': ('safedelete/admin.css',),
}
def queryset(self, request):
# Deprecated in latest Django versions
return self.get_queryset(request)
def get_queryset(self, request):
try:
qs = self.model._default_manager.all_with_deleted()
except:
qs = self.model._default_manager.all()
if hasattr(self, 'get_ordering'):
# Django >= 1.4
ordering = self.get_ordering(request)
if ordering:
qs = qs.order_by(*ordering)
return qs
def log_undeletion(self, request, object, object_repr):
"""
Log that an object will be undeleted.
The default implementation creates an admin LogEntry object.
"""
LogEntry.objects.log_action(
user_id=request.user.pk,
content_type_id=ContentType.objects.get_for_model(self.model).pk,
object_id=object.pk,
object_repr=object_repr,
action_flag=CHANGE
)
def undelete_selected(self, request, queryset):
""" Admin action to undelete objects in bulk with confirmation. """
if not self.has_delete_permission(request):
raise PermissionDenied
assert hasattr(queryset, 'undelete')
# Undeletion confirmed
if request.POST.get('post'):
n = queryset.count()
if n:
for obj in queryset:
obj_display = force_text(obj)
self.log_undeletion(request, obj, obj_display)
queryset.undelete()
if django.VERSION[1] <= 4:
self.message_user(
request,
_("Successfully undeleted %(count)d %(items)s.") % {
"count": n, "items": model_ngettext(self.opts, n)
},
)
else:
self.message_user(
request,
_("Successfully undeleted %(count)d %(items)s.") % {
"count": n, "items": model_ngettext(self.opts, n)
},
messages.SUCCESS,
)
# Return None to display the change list page again.
return None
opts = self.model._meta
if len(queryset) == 1:
objects_name = force_text(opts.verbose_name)
else:
objects_name = force_text(opts.verbose_name_plural)
title = _("Are you sure?")
context = {
'title': title,
'objects_name': objects_name,
'queryset': queryset,
"opts": opts,
"app_label": opts.app_label,
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
}
if django.VERSION[1] < 3:
return render_to_response(
self.undelete_selected_confirmation_template,
context,
context_instance=RequestContext(request))
else:
return TemplateResponse(
request,
self.undelete_selected_confirmation_template,
context,
current_app=self.admin_site.name,
)
undelete_selected.short_description = _("Undelete selected %(verbose_name_plural)s.")