Ticket #7028: patch7028-1.4.rev16590.patch
File patch7028-1.4.rev16590.patch, 14.6 KB (added by , 13 years ago) |
---|
-
django/contrib/admin/options.py
5 5 inlineformset_factory, BaseInlineFormSet) 6 6 from django.contrib.contenttypes.models import ContentType 7 7 from django.contrib.admin import widgets, helpers 8 from django.contrib.admin.util import unquote, flatten_fieldsets, get_deleted_objects, model_format_dict 8 from django.contrib.admin.util import unquote, flatten_fieldsets, get_deleted_objects, model_format_dict, obj_label, get_related_url 9 9 from django.contrib import messages 10 10 from django.views.decorators.csrf import csrf_protect 11 11 from django.core.exceptions import PermissionDenied, ValidationError … … 796 796 return HttpResponseRedirect(request.path + "?_popup=1") 797 797 else: 798 798 return HttpResponseRedirect(request.path) 799 elif "_popup" in request.POST: 800 # object changed via raw id link popup 801 obj_id = repr(force_unicode(obj._get_pk_val()))[1:] 802 obj_url = get_related_url(obj, obj.pk) 803 label = obj_label(obj).replace("'", r"\'") 804 return HttpResponse('<script type="text/javascript">opener.dismissRelatedLookupPopup(' 805 "window, %s, '%s', '%s');</script>" % (obj_id, obj_url, label)) 799 806 elif "_saveasnew" in request.POST: 800 807 msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(verbose_name), 'obj': obj} 801 808 self.message_user(request, msg) -
django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
11 11 return text; 12 12 } 13 13 14 function html_escape(text) { 15 text = text.replace(/&/g, '&'); 16 text = text.replace(/</g, '<'); 17 text = text.replace(/>/g, '>'); 18 text = text.replace(/"/g, '"'); 19 text = text.replace(/'/g, '''); 20 return text; 21 } 22 14 23 // IE doesn't accept periods or dashes in the window name, but the element IDs 15 24 // we use to generate popup window names may contain them, therefore we map them 16 25 // to allowed characters in a reversible way so that we can locate the correct … … 27 36 return text; 28 37 } 29 38 39 function getAdminMediaPrefix() { 40 // Copy-paste from DateTimeShortcuts.js. 41 if (window.__admin_media_prefix__ != undefined) { 42 return window.__admin_media_prefix__; 43 } else { 44 return '/missing-admin-media-prefix/'; 45 } 46 } 47 48 var CLEAR_RAW_ID = '<a href="#" onclick="return clearRawId(this);">' + 49 '<img src="' + getAdminMediaPrefix() + 'img/icon_deletelink.gif" ' + 50 'width="10" height="10" alt="Clear" title="Clear" /></a>'; 51 52 // FIXME: the following produce 'gettext is not defined' errors in FireBug. 53 // Needs to be tracked down. 54 // (jsi18n is generally included before this in admin templates) 55 // 56 // 'width="10" height="10" alt="' + gettext('Clear') + '" title="' + 57 // gettext('Clear') + '" /></a>'; 58 59 function showRelatedObjectPopup(triggeringLink) { 60 var name = triggeringLink.parentNode.id.replace(/^view_lookup_/, ''); 61 name = id_to_windowname(name); 62 return openPopupWindow(triggeringLink.href, '_popup', name); 63 } 64 30 65 function showRelatedObjectLookupPopup(triggeringLink) { 31 66 var name = triggeringLink.id.replace(/^lookup_/, ''); 32 67 name = id_to_windowname(name); 33 var href; 34 if (triggeringLink.href.search(/\?/) >= 0) { 35 href = triggeringLink.href + '&pop=1'; 36 } else { 37 href = triggeringLink.href + '?pop=1'; 38 } 39 var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); 40 win.focus(); 41 return false; 68 return openPopupWindow(triggeringLink.href, 'pop', name); 42 69 } 43 70 44 function dismissRelatedLookupPopup(win, chosenId ) {71 function dismissRelatedLookupPopup(win, chosenId, chosenIdHref, chosenName) { 45 72 var name = windowname_to_id(win.name); 46 73 var elem = document.getElementById(name); 74 var nameElem = document.getElementById("view_lookup_" + name); 47 75 if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { 48 76 elem.value += ',' + chosenId; 49 77 } else { 50 78 document.getElementById(name).value = chosenId; 51 79 } 80 if (nameElem) { 81 nameElem.innerHTML = '<a href="' + chosenIdHref + '" ' + 82 'onclick="return showRelatedObjectPopup(this);">' + 83 html_escape(chosenName) + '</a> ' + CLEAR_RAW_ID; 84 } 52 85 win.close(); 53 86 } 54 87 55 88 function showAddAnotherPopup(triggeringLink) { 56 89 var name = triggeringLink.id.replace(/^add_/, ''); 57 90 name = id_to_windowname(name); 58 href = triggeringLink.href 59 if (href.indexOf('?') == -1) { 60 href += '?_popup=1'; 61 } else { 62 href += '&_popup=1'; 63 } 64 var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); 65 win.focus(); 66 return false; 91 return openPopupWindow(triggeringLink.href, '_popup', name); 67 92 } 68 93 69 94 function dismissAddAnotherPopup(win, newId, newRepr) { 70 95 // newId and newRepr are expected to have previously been escaped by 71 96 // django.utils.html.escape. 72 97 newId = html_unescape(newId); 98 var newRepr_escaped = newRepr; 73 99 newRepr = html_unescape(newRepr); 74 100 var name = windowname_to_id(win.name); 75 101 var elem = document.getElementById(name); … … 84 110 } else { 85 111 elem.value = newId; 86 112 } 113 var nameElem = document.getElementById("view_lookup_" + name); 114 if (nameElem) { 115 var chosenIdHref = win.location.href.replace(/\/add\/[^\/]*$/, 116 '/' + newId + '/'); 117 nameElem.innerHTML = '<a href="' + chosenIdHref + '" ' + 118 'onclick="return showRelatedObjectPopup(this);">' + 119 newRepr_escaped + '</a> ' + CLEAR_RAW_ID; 120 } 87 121 } 88 122 } else { 89 123 var toId = name + "_to"; … … 94 128 } 95 129 win.close(); 96 130 } 131 132 function clearRawId(triggeringLink) { 133 triggeringLink.parentNode.previousSibling.previousSibling.previousSibling.previousSibling.value = ''; 134 triggeringLink.parentNode.innerHTML = ''; 135 return false; 136 } 137 138 function openPopupWindow(href, popup_var, name) { 139 if (href.indexOf('?') == -1) { 140 href += '?'; 141 } else { 142 href += '&'; 143 } 144 href += popup_var + '=1'; 145 var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); 146 win.focus(); 147 return false; 148 } -
django/contrib/admin/templatetags/admin_list.py
3 3 from django.contrib.admin.util import lookup_field, display_for_field, label_for_field 4 4 from django.contrib.admin.views.main import (ALL_VAR, EMPTY_CHANGELIST_VALUE, 5 5 ORDER_VAR, PAGE_VAR, SEARCH_VAR) 6 from django.contrib.admin.util import obj_label, get_related_url 6 7 from django.core.exceptions import ObjectDoesNotExist 7 8 from django.db import models 8 9 from django.templatetags.static import static … … 214 215 attr = pk 215 216 value = result.serializable_value(attr) 216 217 result_id = repr(force_unicode(value))[1:] 217 yield mark_safe(u'<%s%s><a href="%s"%s>%s</a></%s>' % \ 218 (table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), conditional_escape(result_repr), table_tag)) 218 result_name = obj_label(result) 219 result_url = get_related_url(result, result.pk) 220 yield mark_safe(u'<%s%s><a href="%s"%s>%s</a></%s>' % 221 (table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(' "window, %s, '%s', '%s'); return false;\"" % (result_id, result_url, result_name.replace("'", r"\'")) or ''), conditional_escape(result_repr), table_tag)) 219 222 else: 220 223 # By default the fields come from ModelAdmin.list_editable, but if we pull 221 224 # the fields out of the form instead of list_editable custom admins -
django/contrib/admin/widgets.py
13 13 from django.utils.translation import ugettext as _ 14 14 from django.utils.safestring import mark_safe 15 15 from django.utils.encoding import force_unicode 16 from django.contrib.admin.util import get_related_url, obj_label 16 17 17 18 class FilteredSelectMultiple(forms.SelectMultiple): 18 19 """ … … 124 125 attrs = {} 125 126 extra = [] 126 127 if rel_to in self.admin_site._registry: 127 # The related object is registered with the same AdminSite 128 related_url = reverse('admin:%s_%s_changelist' % 129 (rel_to._meta.app_label, 130 rel_to._meta.module_name), 131 current_app=self.admin_site.name) 132 128 related_url = get_related_url(self.rel.to) 133 129 params = self.url_parameters() 134 130 if params: 135 131 url = u'?' + u'&'.join([u'%s=%s' % (k, v) for k, v in params.items()]) … … 139 135 attrs['class'] = 'vForeignKeyRawIdAdminField' # The JavaScript code looks for this hook. 140 136 # TODO: "lookup_id_" is hard-coded here. This should instead use 141 137 # the correct API to determine the ID dynamically. 142 extra.append(u' <a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> '138 extra.append(u' <a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> ' 143 139 % (related_url, url, name)) 144 140 extra.append(u'<img src="%s" width="16" height="16" alt="%s" /></a>' 145 141 % (static('admin/img/selector-search.gif'), _('Lookup'))) 146 142 output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)] + extra 147 if value: 148 output.append(self.label_for_value(value)) 143 output.append(self.label_for_value(value, 'view_lookup_id_%s' % name)) 149 144 return mark_safe(u''.join(output)) 150 145 151 146 def base_url_parameters(self): … … 157 152 params.update({TO_FIELD_VAR: self.rel.get_related_field().name}) 158 153 return params 159 154 160 def label_for_value(self, value): 161 key = self.rel.get_related_field().name 162 try: 163 obj = self.rel.to._default_manager.using(self.db).get(**{key: value}) 164 return ' <strong>%s</strong>' % escape(Truncator(obj).words(14, truncate='...')) 165 except (ValueError, self.rel.to.DoesNotExist): 166 return '' 155 def label_for_value(self, value, name): 156 if value: 157 key = self.rel.get_related_field().name 158 obj = self.rel.to._default_manager.using( 159 self.db).get(**{key: value}) 160 related_url = get_related_url(obj, obj.pk) 161 return (' <strong id="%(name)s"><a href="%(url)s" ' 162 'onclick="return showRelatedObjectPopup(this);">%(label)s</a> ' 163 '<a href="#" onclick="return clearRawId(this);">' 164 '<img src="%(img_src)s" ' 165 'width="10" height="10" alt="%(clear)s" title="%(clear)s" />' 166 '</a></strong>' % {'name': name, 'url': related_url, 167 'label': obj_label(obj), 168 'img_src': static('admin/img/icon_deletelink.gif'), 169 'clear': _("Clear"),} 170 ) 171 else: 172 # a placeholder that will be filled in 173 # JavaScript dismissRelatedLookupPopup() 174 return ' <strong id="%s"></strong>' % name 167 175 176 168 177 class ManyToManyRawIdWidget(ForeignKeyRawIdWidget): 169 178 """ 170 179 A Widget for displaying ManyToMany ids in the "raw_id" interface rather than … … 185 194 def url_parameters(self): 186 195 return self.base_url_parameters() 187 196 188 def label_for_value(self, value ):197 def label_for_value(self, value, name): 189 198 return '' 190 199 191 200 def value_from_datadict(self, data, files, name): … … 238 247 239 248 def render(self, name, value, *args, **kwargs): 240 249 rel_to = self.rel.to 241 info = (rel_to._meta.app_label, rel_to._meta.object_name.lower())242 250 self.widget.choices = self.choices 243 251 output = [self.widget.render(name, value, *args, **kwargs)] 244 252 if self.can_add_related: 245 related_url = reverse('admin:%s_%s_add' % info, current_app=self.admin_site.name)253 related_url = get_related_url(rel_to, 'add', self.admin_site) 246 254 # TODO: "add_id_" is hard-coded here. This should instead use the 247 255 # correct API to determine the ID dynamically. 248 256 output.append(u'<a href="%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> ' -
django/contrib/admin/util.py
6 6 from django.utils import formats 7 7 from django.utils.html import escape 8 8 from django.utils.safestring import mark_safe 9 from django.utils.text import capfirst 9 from django.utils.text import capfirst, truncate_words 10 10 from django.utils.encoding import force_unicode, smart_unicode, smart_str 11 11 from django.utils.translation import ungettext 12 12 from django.core.urlresolvers import reverse … … 302 302 else: 303 303 return smart_unicode(value) 304 304 305 def get_related_url(rel_to, action=None, admin_site=None): 306 reverse_path = 'admin:%s_%s' 307 rel_path = '%s%s/%s/' 308 params = [rel_to._meta.app_label, rel_to._meta.object_name.lower()] 305 309 310 if action: 311 reverse_path += '_%s' 312 rel_path += '%s/' 313 params.append(action) 314 315 if admin_site: 316 try: 317 return reverse(reverse_path % tuple(params), 318 current_app=admin_site.name) 319 except NoReverseMatch: 320 params.insert(0, admin_site.root_path) 321 return rel_path % tuple(params) 322 323 params.insert(0, '../../../') 324 return rel_path % tuple(params) 325 326 def obj_label(obj): 327 return escape(truncate_words(obj, 7)) 328 329 306 330 class NotRelationField(Exception): 307 331 pass 308 332