/usr/share/pyshared/mptt/admin.py is in python-django-mptt 0.5.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | import django
from django.conf import settings
from django.contrib.admin.views.main import ChangeList
from django.contrib.admin.options import ModelAdmin, IncorrectLookupParameters
from django import template
from django.contrib.admin import helpers
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
from django.utils.encoding import force_unicode
from mptt.forms import MPTTAdminForm, TreeNodeChoiceField
__all__ = ('MPTTChangeList', 'MPTTModelAdmin', 'MPTTAdminForm')
class MPTTChangeList(ChangeList):
def get_query_set(self, request=None):
# request arg was added in django r16144 (after 1.3)
if request is not None and django.VERSION >= (1, 4):
qs = super(MPTTChangeList, self).get_query_set(request)
else:
qs = super(MPTTChangeList, self).get_query_set()
# always order by (tree_id, left)
tree_id = qs.model._mptt_meta.tree_id_attr
left = qs.model._mptt_meta.left_attr
return qs.order_by(tree_id, left)
class MPTTModelAdmin(ModelAdmin):
"""
A basic admin class that displays tree items according to their position in the tree.
No extra editing functionality beyond what Django admin normally offers.
"""
change_list_template = 'admin/mptt_change_list.html'
form = MPTTAdminForm
def formfield_for_foreignkey(self, db_field, request, **kwargs):
from mptt.models import MPTTModel, TreeForeignKey
if issubclass(db_field.rel.to, MPTTModel) and not isinstance(db_field, TreeForeignKey):
defaults = dict(form_class=TreeNodeChoiceField, queryset=db_field.rel.to.objects.all(), required=False)
defaults.update(kwargs)
kwargs = defaults
return super(MPTTModelAdmin, self).formfield_for_foreignkey(db_field,
request,
**kwargs)
def get_changelist(self, request, **kwargs):
"""
Returns the ChangeList class for use on the changelist page.
"""
return MPTTChangeList
# In Django 1.1, the changelist class is hard coded in changelist_view, so
# we've got to override this too, just to get it to use our custom ChangeList
if django.VERSION < (1, 2):
def changelist_view(self, request, extra_context=None):
"The 'change list' admin view for this model."
from django.contrib.admin.views.main import ERROR_FLAG
opts = self.model._meta
app_label = opts.app_label
if not self.has_change_permission(request, None):
raise PermissionDenied
# Check actions to see if any are available on this changelist
actions = self.get_actions(request)
# Remove action checkboxes if there aren't any actions available.
list_display = list(self.list_display)
if not actions:
try:
list_display.remove('action_checkbox')
except ValueError:
pass
CL = self.get_changelist(request)
try:
cl = CL(request, self.model, list_display, self.list_display_links, self.list_filter,
self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self)
except IncorrectLookupParameters:
# Wacky lookup parameters were given, so redirect to the main
# changelist page, without parameters, and pass an 'invalid=1'
# parameter via the query string. If wacky parameters were given and
# the 'invalid=1' parameter was already in the query string, something
# is screwed up with the database, so display an error page.
if ERROR_FLAG in request.GET.keys():
return render_to_response('admin/invalid_setup.html', {'title': _('Database error')})
return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')
# If the request was POSTed, this might be a bulk action or a bulk edit.
# Try to look up an action or confirmation first, but if this isn't an
# action the POST will fall through to the bulk edit check, below.
if actions and request.method == 'POST' and (helpers.ACTION_CHECKBOX_NAME in request.POST or 'index' in request.POST):
response = self.response_action(request, queryset=cl.get_query_set(request))
if response:
return response
# If we're allowing changelist editing, we need to construct a formset
# for the changelist given all the fields to be edited. Then we'll
# use the formset to validate/process POSTed data.
formset = cl.formset = None
# Handle POSTed bulk-edit data.
if request.method == "POST" and self.list_editable:
FormSet = self.get_changelist_formset(request)
formset = cl.formset = FormSet(request.POST, request.FILES, queryset=cl.result_list)
if formset.is_valid():
changecount = 0
for form in formset.forms:
if form.has_changed():
obj = self.save_form(request, form, change=True)
self.save_model(request, obj, form, change=True)
form.save_m2m()
change_msg = self.construct_change_message(request, form, None)
self.log_change(request, obj, change_msg)
changecount += 1
if changecount:
if changecount == 1:
name = force_unicode(opts.verbose_name)
else:
name = force_unicode(opts.verbose_name_plural)
msg = ungettext("%(count)s %(name)s was changed successfully.",
"%(count)s %(name)s were changed successfully.",
changecount) % {'count': changecount,
'name': name,
'obj': force_unicode(obj)}
self.message_user(request, msg)
return HttpResponseRedirect(request.get_full_path())
# Handle GET -- construct a formset for display.
elif self.list_editable:
FormSet = self.get_changelist_formset(request)
formset = cl.formset = FormSet(queryset=cl.result_list)
# Build the list of media to be used by the formset.
if formset:
media = self.media + formset.media
else:
media = self.media
# Build the action form and populate it with available actions.
if actions:
action_form = self.action_form(auto_id=None)
action_form.fields['action'].choices = self.get_action_choices(request)
else:
action_form = None
context = {
'title': cl.title,
'is_popup': cl.is_popup,
'cl': cl,
'media': media,
'has_add_permission': self.has_add_permission(request),
'root_path': self.admin_site.root_path,
'app_label': app_label,
'action_form': action_form,
'actions_on_top': self.actions_on_top,
'actions_on_bottom': self.actions_on_bottom,
}
context.update(extra_context or {})
context_instance = template.RequestContext(request, current_app=self.admin_site.name)
return render_to_response(self.change_list_template or [
'admin/%s/%s/change_list.html' % (app_label, opts.object_name.lower()),
'admin/%s/change_list.html' % app_label,
'admin/change_list.html'
], context, context_instance=context_instance)
if getattr(settings, 'MPTT_USE_FEINCMS', True):
try:
from feincms.admin import editor
except ImportError:
pass
else:
__all__ = tuple(list(__all__) + ['FeinCMSModelAdmin'])
class FeinCMSModelAdmin(editor.TreeEditor):
"""
A ModelAdmin to add changelist tree view and editing capabilities.
Requires FeinCMS to be installed.
"""
form = MPTTAdminForm
def _actions_column(self, obj):
actions = super(FeinCMSModelAdmin, self)._actions_column(obj)
actions.insert(0,
u'<a href="add/?%s=%s" title="%s"><img src="%simg/admin/icon_addlink.gif" alt="%s" /></a>' % (
self.model._mptt_meta.parent_attr,
obj.pk,
_('Add child'),
settings.ADMIN_MEDIA_PREFIX,
_('Add child')))
if hasattr(obj, 'get_absolute_url'):
actions.insert(0,
u'<a href="%s" title="%s" target="_blank"><img src="%simg/admin/selector-search.gif" alt="%s" /></a>' % (
obj.get_absolute_url(),
_('View on site'),
settings.ADMIN_MEDIA_PREFIX,
_('View on site')))
return actions
def delete_selected_tree(self, modeladmin, request, queryset):
"""
Deletes multiple instances and makes sure the MPTT fields get recalculated properly.
(Because merely doing a bulk delete doesn't trigger the post_delete hooks.)
"""
n = 0
for obj in queryset:
obj.delete()
n += 1
self.message_user(request, _("Successfully deleted %s items.") % n)
def get_actions(self, request):
actions = super(FeinCMSModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
actions['delete_selected'] = (self.delete_selected_tree, 'delete_selected', _("Delete selected %(verbose_name_plural)s"))
return actions
|