Ticket #3522: deleted_objects_fix2.diff

File deleted_objects_fix2.diff, 12.5 KB (added by Glin <glin@…>, 8 years ago)
  • options.py

     
    33from django.newforms.formsets import all_valid
    44from django.newforms.models import inline_formset
    55from django.contrib.admin import widgets
    6 from django.core.exceptions import ImproperlyConfigured, PermissionDenied
     6from django.core.exceptions import ImproperlyConfigured, PermissionDenied, ObjectDoesNotExist
    77from django.db import models
    88from django.http import Http404, HttpResponse, HttpResponseRedirect
    99from django.shortcuts import get_object_or_404, render_to_response
     
    3434            myappend('_' + item)
    3535    return "".join(res)
    3636
     37def _nest_help(obj, depth, val):
     38    current = obj
     39    for i in range(depth):
     40        current = current[-1]
     41    current.append(val)
     42
     43def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_depth):
     44    "Helper function that recursively populates deleted_objects."
     45    nh = _nest_help # Bind to local variable for performance
     46    if current_depth > 16:
     47        return # Avoid recursing too deep.
     48    opts_seen = []
     49    for related in opts.get_all_related_objects():
     50        if related.opts in opts_seen:
     51            continue
     52        opts_seen.append(related.opts)
     53        rel_opts_name = related.get_accessor_name()
     54        if isinstance(related.field.rel, models.OneToOneRel):
     55            try:
     56                sub_obj = getattr(obj, rel_opts_name)
     57            except ObjectDoesNotExist:
     58                pass
     59            else:
     60                if related.opts.admin:
     61                    p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
     62                    if not user.has_perm(p):
     63                        perms_needed.add(related.opts.verbose_name)
     64                        # We don't care about populating deleted_objects now.
     65                        continue
     66                if related.field.rel.edit_inline or not related.opts.admin:
     67                    # Don't display link to edit, because it either has no
     68                    # admin or is edited inline.
     69                    nh(deleted_objects, current_depth, ['%s: %s' % (capfirst(related.opts.verbose_name), sub_obj), []])
     70                else:
     71                    # Display a link to the admin page.
     72                    nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
     73                        (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(),
     74                        sub_obj._get_pk_val(), sub_obj), []])
     75                _get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
     76        else:
     77            has_related_objs = False
     78            for sub_obj in getattr(obj, rel_opts_name).all():
     79                has_related_objs = True
     80                if related.field.rel.edit_inline or not related.opts.admin:
     81                    # Don't display link to edit, because it either has no
     82                    # admin or is edited inline.
     83                    nh(deleted_objects, current_depth, ['%s: %s' % (capfirst(related.opts.verbose_name), escape(str(sub_obj))), []])
     84                else:
     85                    # Display a link to the admin page.
     86                    nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
     87                        (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(), sub_obj._get_pk_val(), escape(str(sub_obj))), []])
     88                _get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
     89            # If there were related objects, and the user doesn't have
     90            # permission to delete them, add the missing perm to perms_needed.
     91            if related.opts.admin and has_related_objs:
     92                p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
     93                if not user.has_perm(p):
     94                    perms_needed.add(related.opts.verbose_name)
     95    for related in opts.get_all_related_many_to_many_objects():
     96        if related.opts in opts_seen:
     97            continue
     98        opts_seen.append(related.opts)
     99        rel_opts_name = related.get_accessor_name()
     100        has_related_objs = False
     101
     102        # related.get_accessor_name() could return None for symmetrical relationships
     103        if rel_opts_name:
     104            rel_objs = getattr(obj, rel_opts_name, None)
     105            if rel_objs:
     106                has_related_objs = True
     107
     108        if has_related_objs:
     109            for sub_obj in rel_objs.all():
     110                if related.field.rel.edit_inline or not related.opts.admin:
     111                    # Don't display link to edit, because it either has no
     112                    # admin or is edited inline.
     113                    nh(deleted_objects, current_depth, [_('One or more %(fieldname)s in %(name)s: %(obj)s') % \
     114                        {'fieldname': related.field.verbose_name, 'name': related.opts.verbose_name, 'obj': escape(str(sub_obj))}, []])
     115                else:
     116                    # Display a link to the admin page.
     117                    nh(deleted_objects, current_depth, [
     118                        (_('One or more %(fieldname)s in %(name)s:') % {'fieldname': related.field.verbose_name, 'name':related.opts.verbose_name}) + \
     119                        (' <a href="../../../../%s/%s/%s/">%s</a>' % \
     120                            (related.opts.app_label, related.opts.module_name, sub_obj._get_pk_val(), escape(str(sub_obj)))), []])
     121        # If there were related objects, and the user doesn't have
     122        # permission to change them, add the missing perm to perms_needed.
     123        if related.opts.admin and has_related_objs:
     124            p = '%s.%s' % (related.opts.app_label, related.opts.get_change_permission())
     125            if not user.has_perm(p):
     126                perms_needed.add(related.opts.verbose_name)
     127
    37128class AdminForm(object):
    38129    def __init__(self, form, fieldsets, prepopulated_fields):
    39130        self.form, self.fieldsets = form, fieldsets
  • views/main.py

     
    44from django.contrib.admin.views.decorators import staff_member_required
    55from django.views.decorators.cache import never_cache
    66from django.contrib.contenttypes.models import ContentType
    7 from django.core.exceptions import ObjectDoesNotExist
    87from django.core.paginator import ObjectPaginator, InvalidPage
    98from django.shortcuts import get_object_or_404, render_to_response
    109from django.db import models
    1110from django.db.models.query import handle_legacy_orderlist, QuerySet
    1211from django.http import Http404
    13 from django.utils.html import escape
    14 from django.utils.text import capfirst
    1512import operator
    1613
    1714# The system will display a "Show all" link on the change list only if the
     
    136133    return render_to_response('admin/index.html', {'title': _('Site administration')}, context_instance=template.RequestContext(request))
    137134index = staff_member_required(never_cache(index))
    138135
    139 def _nest_help(obj, depth, val):
    140     current = obj
    141     for i in range(depth):
    142         current = current[-1]
    143     current.append(val)
    144136
    145 def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_depth):
    146     "Helper function that recursively populates deleted_objects."
    147     nh = _nest_help # Bind to local variable for performance
    148     if current_depth > 16:
    149         return # Avoid recursing too deep.
    150     opts_seen = []
    151     for related in opts.get_all_related_objects():
    152         if related.opts in opts_seen:
    153             continue
    154         opts_seen.append(related.opts)
    155         rel_opts_name = related.get_accessor_name()
    156         if isinstance(related.field.rel, models.OneToOneRel):
    157             try:
    158                 sub_obj = getattr(obj, rel_opts_name)
    159             except ObjectDoesNotExist:
    160                 pass
    161             else:
    162                 if related.opts.admin:
    163                     p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
    164                     if not user.has_perm(p):
    165                         perms_needed.add(related.opts.verbose_name)
    166                         # We don't care about populating deleted_objects now.
    167                         continue
    168                 if related.field.rel.edit_inline or not related.opts.admin:
    169                     # Don't display link to edit, because it either has no
    170                     # admin or is edited inline.
    171                     nh(deleted_objects, current_depth, ['%s: %s' % (capfirst(related.opts.verbose_name), sub_obj), []])
    172                 else:
    173                     # Display a link to the admin page.
    174                     nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
    175                         (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(),
    176                         sub_obj._get_pk_val(), sub_obj), []])
    177                 _get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
    178         else:
    179             has_related_objs = False
    180             for sub_obj in getattr(obj, rel_opts_name).all():
    181                 has_related_objs = True
    182                 if related.field.rel.edit_inline or not related.opts.admin:
    183                     # Don't display link to edit, because it either has no
    184                     # admin or is edited inline.
    185                     nh(deleted_objects, current_depth, ['%s: %s' % (capfirst(related.opts.verbose_name), escape(str(sub_obj))), []])
    186                 else:
    187                     # Display a link to the admin page.
    188                     nh(deleted_objects, current_depth, ['%s: <a href="../../../../%s/%s/%s/">%s</a>' % \
    189                         (capfirst(related.opts.verbose_name), related.opts.app_label, related.opts.object_name.lower(), sub_obj._get_pk_val(), escape(str(sub_obj))), []])
    190                 _get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2)
    191             # If there were related objects, and the user doesn't have
    192             # permission to delete them, add the missing perm to perms_needed.
    193             if related.opts.admin and has_related_objs:
    194                 p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
    195                 if not user.has_perm(p):
    196                     perms_needed.add(related.opts.verbose_name)
    197     for related in opts.get_all_related_many_to_many_objects():
    198         if related.opts in opts_seen:
    199             continue
    200         opts_seen.append(related.opts)
    201         rel_opts_name = related.get_accessor_name()
    202         has_related_objs = False
    203 
    204         # related.get_accessor_name() could return None for symmetrical relationships
    205         if rel_opts_name:
    206             rel_objs = getattr(obj, rel_opts_name, None)
    207             if rel_objs:
    208                 has_related_objs = True
    209 
    210         if has_related_objs:
    211             for sub_obj in rel_objs.all():
    212                 if related.field.rel.edit_inline or not related.opts.admin:
    213                     # Don't display link to edit, because it either has no
    214                     # admin or is edited inline.
    215                     nh(deleted_objects, current_depth, [_('One or more %(fieldname)s in %(name)s: %(obj)s') % \
    216                         {'fieldname': related.field.verbose_name, 'name': related.opts.verbose_name, 'obj': escape(str(sub_obj))}, []])
    217                 else:
    218                     # Display a link to the admin page.
    219                     nh(deleted_objects, current_depth, [
    220                         (_('One or more %(fieldname)s in %(name)s:') % {'fieldname': related.field.verbose_name, 'name':related.opts.verbose_name}) + \
    221                         (' <a href="../../../../%s/%s/%s/">%s</a>' % \
    222                             (related.opts.app_label, related.opts.module_name, sub_obj._get_pk_val(), escape(str(sub_obj)))), []])
    223         # If there were related objects, and the user doesn't have
    224         # permission to change them, add the missing perm to perms_needed.
    225         if related.opts.admin and has_related_objs:
    226             p = '%s.%s' % (related.opts.app_label, related.opts.get_change_permission())
    227             if not user.has_perm(p):
    228                 perms_needed.add(related.opts.verbose_name)
    229 
    230137class ChangeList(object):
    231138    def __init__(self, request, model, list_display, list_display_links, list_filter, date_hierarchy, search_fields, list_select_related, list_per_page, model_admin):
    232139        self.model = model
Back to Top