Ticket #12025: t12025_r11366.3.patch
File t12025_r11366.3.patch, 8.9 KB (added by , 15 years ago) |
---|
-
django/db/models/options.py
412 412 cache[obj] = parent 413 413 else: 414 414 cache[obj] = model 415 from django.contrib.contenttypes import generic 415 416 for klass in get_models(): 416 417 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: 418 421 cache[RelatedObject(f.rel.to, klass, f)] = None 419 422 if app_cache_ready(): 420 423 self._related_many_to_many_cache = cache -
django/contrib/admin/util.py
71 71 except NoReverseMatch: 72 72 return '%s%s/%s/%s/' % ('../'*levels_to_root, app_label, module_name, pk) 73 73 74 def get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_depth, admin_site, levels_to_root=4 ):74 def get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_depth, admin_site, levels_to_root=4, objs_seen=[]): 75 75 """ 76 76 Helper function that recursively populates deleted_objects. 77 77 … … 86 86 if current_depth > 16: 87 87 return # Avoid recursing too deep. 88 88 opts_seen = [] 89 if current_depth == 1: 90 objs_seen = [] # avoid to have the older objs_seen 89 91 for related in opts.get_all_related_objects(): 90 92 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: 92 95 continue 93 opts_seen.append(related.opts) 94 rel_opts_name = related.get_accessor_name() 96 opts_seen.append(rel_opts_name) 95 97 if isinstance(related.field.rel, models.OneToOneRel): 96 98 try: 97 99 sub_obj = getattr(obj, rel_opts_name) 98 100 except ObjectDoesNotExist: 99 101 pass 100 102 else: 103 if sub_obj in objs_seen: 104 continue # avoid to have the same object 105 objs_seen.append(sub_obj) 101 106 if has_admin: 102 107 p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission()) 103 108 if not user.has_perm(p): … … 109 114 # admin or is edited inline. 110 115 nh(deleted_objects, current_depth, 111 116 [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), []]) 112 124 else: 113 125 # Display a link to the admin page. 114 126 nh(deleted_objects, current_depth, [mark_safe(u'%s: <a href="%s">%s</a>' % … … 119 131 admin_site, 120 132 levels_to_root), 121 133 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) 123 135 else: 124 136 has_related_objs = False 125 137 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) 126 141 has_related_objs = True 127 142 if not has_admin: 128 143 # Don't display link to edit, because it either has no 129 144 # admin or is edited inline. 130 145 nh(deleted_objects, current_depth, 131 146 [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), []]) 132 154 else: 133 155 # Display a link to the admin page. 134 156 nh(deleted_objects, current_depth, [mark_safe(u'%s: <a href="%s">%s</a>' % … … 139 161 admin_site, 140 162 levels_to_root), 141 163 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) 143 165 # If there were related objects, and the user doesn't have 144 166 # permission to delete them, add the missing perm to perms_needed. 145 167 if has_admin and has_related_objs: 146 168 p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission()) 147 169 if not user.has_perm(p): 148 170 perms_needed.add(related.opts.verbose_name) 171 from django.contrib.contenttypes import generic 149 172 for related in opts.get_all_related_many_to_many_objects(): 150 173 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: 152 176 continue 153 opts_seen.append(related.opts) 154 rel_opts_name = related.get_accessor_name() 177 opts_seen.append(rel_opts_name) 155 178 has_related_objs = False 156 179 157 180 # related.get_accessor_name() could return None for symmetrical relationships 158 181 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)) 160 184 if rel_objs: 161 185 has_related_objs = True 162 186 163 187 if has_related_objs: 164 188 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) 165 192 if not has_admin: 166 193 # Don't display link to edit, because it either has no 167 194 # admin or is edited inline. 168 195 nh(deleted_objects, current_depth, [_('One or more %(fieldname)s in %(name)s: %(obj)s') % \ 169 196 {'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), []]) 170 206 else: 171 207 # Display a link to the admin page. 172 208 nh(deleted_objects, current_depth, [