This file is indexed.

/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