Ticket #12025: t12025_r11366.3.patch

File t12025_r11366.3.patch, 8.9 KB (added by anonymous, 5 years ago)

add related object to callback

  • django/db/models/options.py

     
    412412                    cache[obj] = parent
    413413                else:
    414414                    cache[obj] = model
     415        from django.contrib.contenttypes import generic                   
    415416        for klass in get_models():
    416417            for f in klass._meta.local_many_to_many:
    417                 if f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta:
     418                if f.rel and isinstance(f, generic.GenericRelation) and self == klass._meta:
     419                    cache[RelatedObject(klass, f.rel.to, f)] = None
     420                elif f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta:
    418421                    cache[RelatedObject(f.rel.to, klass, f)] = None
    419422        if app_cache_ready():
    420423            self._related_many_to_many_cache = cache
  • django/contrib/admin/util.py

     
    7171    except NoReverseMatch:
    7272        return '%s%s/%s/%s/' % ('../'*levels_to_root, app_label, module_name, pk)
    7373
    74 def get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_depth, admin_site, levels_to_root=4):
     74def get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_depth, admin_site, levels_to_root=4, objs_seen=[]):
    7575    """
    7676    Helper function that recursively populates deleted_objects.
    7777
     
    8686    if current_depth > 16:
    8787        return # Avoid recursing too deep.
    8888    opts_seen = []
     89    if current_depth == 1:
     90        objs_seen = [] # avoid to have the older objs_seen
    8991    for related in opts.get_all_related_objects():
    9092        has_admin = related.model in admin_site._registry
    91         if related.opts in opts_seen:
     93        rel_opts_name = related.get_accessor_name()
     94        if rel_opts_name in opts_seen:
    9295            continue
    93         opts_seen.append(related.opts)
    94         rel_opts_name = related.get_accessor_name()
     96        opts_seen.append(rel_opts_name)
    9597        if isinstance(related.field.rel, models.OneToOneRel):
    9698            try:
    9799                sub_obj = getattr(obj, rel_opts_name)
    98100            except ObjectDoesNotExist:
    99101                pass
    100102            else:
     103                if sub_obj in objs_seen:
     104                    continue # avoid to have the same object
     105                objs_seen.append(sub_obj)
    101106                if has_admin:
    102107                    p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
    103108                    if not user.has_perm(p):
     
    109114                    # admin or is edited inline.
    110115                    nh(deleted_objects, current_depth,
    111116                        [u'%s: %s' % (capfirst(related.opts.verbose_name), force_unicode(sub_obj)), []])
     117                elif has_admin and hasattr(admin_site._registry[related.model], 'get_delete_confirmation_message'):
     118                    # Display a link to the admin page but use an admin function in order to change the message, obj and link
     119                    result_msg = admin_site._registry[related.model].get_delete_confirmation_message(
     120                        obj, u'%s:' % capfirst(related.opts.verbose_name), sub_obj, admin_site, levels_to_root)
     121                    if not result_msg:
     122                        continue
     123                    nh(deleted_objects, current_depth, [mark_safe(result_msg), []])
    112124                else:
    113125                    # Display a link to the admin page.
    114126                    nh(deleted_objects, current_depth, [mark_safe(u'%s: <a href="%s">%s</a>' %
     
    119131                                            admin_site,
    120132                                            levels_to_root),
    121133                        escape(sub_obj))), []])
    122                 get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2, admin_site)
     134                get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2, admin_site, objs_seen=objs_seen)
    123135        else:
    124136            has_related_objs = False
    125137            for sub_obj in getattr(obj, rel_opts_name).all():
     138                if sub_obj in objs_seen:
     139                    continue # avoid to have the same object
     140                objs_seen.append(sub_obj)
    126141                has_related_objs = True
    127142                if not has_admin:
    128143                    # Don't display link to edit, because it either has no
    129144                    # admin or is edited inline.
    130145                    nh(deleted_objects, current_depth,
    131146                        [u'%s: %s' % (capfirst(related.opts.verbose_name), force_unicode(sub_obj)), []])
     147                elif has_admin and hasattr(admin_site._registry[related.model], 'get_delete_confirmation_message'):
     148                    # Display a link to the admin page but use an admin function in order to change the message, obj and link
     149                    result_msg = admin_site._registry[related.model].get_delete_confirmation_message(
     150                        obj, u'%s:' % capfirst(related.opts.verbose_name), sub_obj, admin_site, levels_to_root)
     151                    if not result_msg:
     152                        continue
     153                    nh(deleted_objects, current_depth, [mark_safe(result_msg), []])
    132154                else:
    133155                    # Display a link to the admin page.
    134156                    nh(deleted_objects, current_depth, [mark_safe(u'%s: <a href="%s">%s</a>' %
     
    139161                                            admin_site,
    140162                                            levels_to_root),
    141163                        escape(sub_obj))), []])
    142                 get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2, admin_site)
     164                get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2, admin_site, objs_seen=objs_seen)
    143165            # If there were related objects, and the user doesn't have
    144166            # permission to delete them, add the missing perm to perms_needed.
    145167            if has_admin and has_related_objs:
    146168                p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
    147169                if not user.has_perm(p):
    148170                    perms_needed.add(related.opts.verbose_name)
     171    from django.contrib.contenttypes import generic
    149172    for related in opts.get_all_related_many_to_many_objects():
    150173        has_admin = related.model in admin_site._registry
    151         if related.opts in opts_seen:
     174        rel_opts_name = related.get_accessor_name()
     175        if rel_opts_name in opts_seen:
    152176            continue
    153         opts_seen.append(related.opts)
    154         rel_opts_name = related.get_accessor_name()
     177        opts_seen.append(rel_opts_name)
    155178        has_related_objs = False
    156179
    157180        # related.get_accessor_name() could return None for symmetrical relationships
    158181        if rel_opts_name:
    159             rel_objs = getattr(obj, rel_opts_name, None)
     182            rel_objs = getattr(obj, rel_opts_name, None) or \
     183                (isinstance(related.field, generic.GenericRelation) and getattr(obj, related.field.verbose_name, None))               
    160184            if rel_objs:
    161185                has_related_objs = True
    162186
    163187        if has_related_objs:
    164188            for sub_obj in rel_objs.all():
     189                if sub_obj in objs_seen:
     190                    continue # avoid to have the same object
     191                objs_seen.append(sub_obj)
    165192                if not has_admin:
    166193                    # Don't display link to edit, because it either has no
    167194                    # admin or is edited inline.
    168195                    nh(deleted_objects, current_depth, [_('One or more %(fieldname)s in %(name)s: %(obj)s') % \
    169196                        {'fieldname': force_unicode(related.field.verbose_name), 'name': force_unicode(related.opts.verbose_name), 'obj': escape(sub_obj)}, []])
     197                elif has_admin and hasattr(admin_site._registry[related.model], 'get_delete_confirmation_message'):
     198                    # Display a link to the admin page but use an admin function in order to change the message, obj and link
     199                    result_msg = admin_site._registry[related.model].get_delete_confirmation_message(
     200                        obj, (_('One or more %(fieldname)s in %(name)s:') % \
     201                            {'fieldname': escape(force_unicode(related.field.verbose_name)), 'name': escape(force_unicode(related.opts.verbose_name))}),
     202                        sub_obj, admin_site, levels_to_root)
     203                    if not result_msg:
     204                        continue
     205                    nh(deleted_objects, current_depth, [mark_safe(result_msg), []])
    170206                else:
    171207                    # Display a link to the admin page.
    172208                    nh(deleted_objects, current_depth, [
Back to Top