diff --git a/AUTHORS b/AUTHORS
index 55211a6..d3ad681 100644
a
|
b
|
answer newbie questions, and generally made Django that much better:
|
69 | 69 | Esdras Beleza <linux@esdrasbeleza.com> |
70 | 70 | Chris Bennett <chrisrbennett@yahoo.com> |
71 | 71 | James Bennett |
| 72 | Marco Beri <marcoberi@gmail.com> |
72 | 73 | Julian Bez |
73 | 74 | Arvis Bickovskis <viestards.lists@gmail.com> |
74 | 75 | Natalia Bidart |
diff --git a/django/contrib/admin/media/js/admin/RelatedObjectLookups.js b/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
index 1bc78f8..359131b 100644
a
|
b
|
function html_unescape(text) {
|
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 | | // to allowed characters in a reversible way so that we can locate the correct |
| 25 | // to allowed characters in a reversible way so that we can locate the correct |
17 | 26 | // element when the popup window is dismissed. |
18 | 27 | function id_to_windowname(text) { |
19 | 28 | text = text.replace(/\./g, '__dot__'); |
… |
… |
function windowname_to_id(text) {
|
27 | 36 | return text; |
28 | 37 | } |
29 | 38 | |
| 39 | function showRelatedObjectPopup(triggeringLink) { |
| 40 | var name = triggeringLink.parentNode.id.replace(/^view_lookup_/, ''); |
| 41 | name = id_to_windowname(name); |
| 42 | return openPopupWindow(triggeringLink.href, '_popup', name); |
| 43 | } |
| 44 | |
30 | 45 | function showRelatedObjectLookupPopup(triggeringLink) { |
31 | 46 | var name = triggeringLink.id.replace(/^lookup_/, ''); |
32 | 47 | 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; |
| 48 | return openPopupWindow(triggeringLink.href, 'pop', name); |
42 | 49 | } |
43 | 50 | |
44 | | function dismissRelatedLookupPopup(win, chosenId) { |
| 51 | function dismissRelatedLookupPopup(win, chosenId, chosenIdHref, chosenName) { |
45 | 52 | var name = windowname_to_id(win.name); |
46 | 53 | var elem = document.getElementById(name); |
| 54 | var nameElem = document.getElementById("view_lookup_" + name); |
| 55 | |
47 | 56 | if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { |
48 | 57 | elem.value += ',' + chosenId; |
49 | 58 | } else { |
50 | 59 | document.getElementById(name).value = chosenId; |
51 | 60 | } |
| 61 | |
| 62 | if (nameElem) { |
| 63 | nameElem.innerHTML = '<a href="' + chosenIdHref + '" ' + |
| 64 | 'onclick="return showRelatedObjectPopup(this);">' + |
| 65 | html_escape(chosenName) + '</a>'; |
| 66 | } |
| 67 | |
52 | 68 | win.close(); |
53 | 69 | } |
54 | 70 | |
55 | 71 | function showAddAnotherPopup(triggeringLink) { |
56 | 72 | var name = triggeringLink.id.replace(/^add_/, ''); |
57 | 73 | 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; |
| 74 | return openPopupWindow(triggeringLink.href, '_popup', name); |
67 | 75 | } |
68 | 76 | |
69 | 77 | function dismissAddAnotherPopup(win, newId, newRepr) { |
70 | 78 | // newId and newRepr are expected to have previously been escaped by |
71 | 79 | // django.utils.html.escape. |
72 | 80 | newId = html_unescape(newId); |
| 81 | var newRepr_escaped = newRepr; |
73 | 82 | newRepr = html_unescape(newRepr); |
74 | 83 | var name = windowname_to_id(win.name); |
75 | 84 | var elem = document.getElementById(name); |
… |
… |
function dismissAddAnotherPopup(win, newId, newRepr) {
|
84 | 93 | } else { |
85 | 94 | elem.value = newId; |
86 | 95 | } |
| 96 | |
| 97 | var nameElem = document.getElementById("view_lookup_" + name); |
| 98 | if (nameElem) { |
| 99 | var chosenIdHref = win.location.href.replace(/\/add\/[^\/]*$/, |
| 100 | '/' + newId + '/'); |
| 101 | nameElem.innerHTML = '<a href="' + chosenIdHref + '" ' + |
| 102 | 'onclick="return showRelatedObjectPopup(this);">' + |
| 103 | newRepr_escaped + '</a>'; |
| 104 | } |
87 | 105 | } |
88 | 106 | } else { |
89 | 107 | var toId = name + "_to"; |
… |
… |
function dismissAddAnotherPopup(win, newId, newRepr) {
|
94 | 112 | } |
95 | 113 | win.close(); |
96 | 114 | } |
| 115 | |
| 116 | function clearRawId(triggeringLink) { |
| 117 | triggeringLink.previousSibling.previousSibling.value = ''; |
| 118 | triggeringLink.nextSibling.nextSibling.nextSibling.nextSibling.innerHTML = ''; |
| 119 | return false; |
| 120 | } |
| 121 | |
| 122 | function openPopupWindow(href, popup_var, name) { |
| 123 | if (href.indexOf('?') == -1) { |
| 124 | href += '?'; |
| 125 | } else { |
| 126 | href += '&'; |
| 127 | } |
| 128 | href += popup_var + '=1'; |
| 129 | var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); |
| 130 | win.focus(); |
| 131 | return false; |
| 132 | } |
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 8f68eb1..140b79c 100644
a
|
b
|
from django.forms.models import BaseInlineFormSet
|
5 | 5 | from django.contrib.contenttypes.models import ContentType |
6 | 6 | from django.contrib.admin import widgets |
7 | 7 | from django.contrib.admin import helpers |
8 | | from django.contrib.admin.util import unquote, flatten_fieldsets, get_deleted_objects, model_ngettext, model_format_dict |
| 8 | from django.contrib.admin.util import unquote, flatten_fieldsets, get_deleted_objects, model_ngettext, 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 |
… |
… |
class ModelAdmin(BaseModelAdmin):
|
674 | 674 | return HttpResponseRedirect(request.path + "?_popup=1") |
675 | 675 | else: |
676 | 676 | return HttpResponseRedirect(request.path) |
| 677 | elif request.POST.has_key("_popup"): |
| 678 | # object changed via raw id link popup |
| 679 | obj_id = repr(force_unicode(obj._get_pk_val()))[1:] |
| 680 | obj_url = get_related_url(obj, obj.pk) |
| 681 | label = obj_label(obj).replace("'", r"\'") |
| 682 | return HttpResponse('<script type="text/javascript">opener.dismissRelatedLookupPopup(' |
| 683 | "window, %s, '%s', '%s');</script>" % (obj_id, obj_url, label)) |
677 | 684 | elif request.POST.has_key("_saveasnew"): |
678 | 685 | msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(opts.verbose_name), 'obj': obj} |
679 | 686 | self.message_user(request, msg) |
diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
index 7cd3f0a..bf8fba2 100644
a
|
b
|
from django.conf import settings
|
4 | 4 | from django.contrib.admin.util import lookup_field, display_for_field, label_for_field |
5 | 5 | from django.contrib.admin.views.main import ALL_VAR, EMPTY_CHANGELIST_VALUE |
6 | 6 | from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR |
| 7 | from django.contrib.admin.util import obj_label, get_related_url |
7 | 8 | from django.core.exceptions import ObjectDoesNotExist |
8 | 9 | from django.db import models |
9 | 10 | from django.forms.forms import pretty_name |
… |
… |
def items_for_result(cl, result, form):
|
166 | 167 | attr = pk |
167 | 168 | value = result.serializable_value(attr) |
168 | 169 | result_id = repr(force_unicode(value))[1:] |
169 | | yield mark_safe(u'<%s%s><a href="%s"%s>%s</a></%s>' % \ |
170 | | (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)) |
| 170 | result_name = obj_label(result) |
| 171 | result_url = get_related_url(result, result.pk) |
| 172 | yield mark_safe(u'<%s%s><a href="%s"%s>%s</a></%s>' % |
| 173 | (table_tag, row_class, url, |
| 174 | (cl.is_popup |
| 175 | and ' onclick="opener.dismissRelatedLookupPopup(' |
| 176 | "window, %s, '%s', '%s'); return false;\"" % |
| 177 | (result_id, result_url, |
| 178 | result_name.replace("'", r"\'")) |
| 179 | or ''), |
| 180 | conditional_escape(result_repr), table_tag)) |
171 | 181 | else: |
172 | 182 | # By default the fields come from ModelAdmin.list_editable, but if we pull |
173 | 183 | # the fields out of the form instead of list_editable custom admins |
diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py
index d252a80..dbaea60 100644
a
|
b
|
from django.db import models
|
3 | 3 | from django.utils import formats |
4 | 4 | from django.utils.html import escape |
5 | 5 | from django.utils.safestring import mark_safe |
6 | | from django.utils.text import capfirst |
| 6 | from django.utils.text import capfirst, truncate_words |
7 | 7 | from django.utils.encoding import force_unicode, smart_unicode, smart_str |
8 | 8 | from django.utils.translation import ungettext, ugettext as _ |
9 | 9 | from django.core.urlresolvers import reverse, NoReverseMatch |
… |
… |
def display_for_field(value, field):
|
305 | 305 | return formats.number_format(value) |
306 | 306 | else: |
307 | 307 | return smart_unicode(value) |
| 308 | |
| 309 | def get_related_url(rel_to, action=None, admin_site=None): |
| 310 | reverse_path = 'admin:%s_%s' |
| 311 | rel_path = '%s%s/%s/' |
| 312 | params = [rel_to._meta.app_label, rel_to._meta.object_name.lower()] |
| 313 | |
| 314 | if action: |
| 315 | reverse_path += '_%s' |
| 316 | rel_path += '%s/' |
| 317 | params.append(action) |
| 318 | |
| 319 | if admin_site: |
| 320 | try: |
| 321 | return reverse(reverse_path % tuple(params), |
| 322 | current_app=admin_site.name) |
| 323 | except NoReverseMatch: |
| 324 | params.insert(0, admin_site.root_path) |
| 325 | return rel_path % tuple(params) |
| 326 | |
| 327 | params.insert(0, '../../../') |
| 328 | return rel_path % tuple(params) |
| 329 | |
| 330 | def obj_label(obj): |
| 331 | return escape(truncate_words(obj, 7)) |
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
index 120df94..f22d781 100644
a
|
b
|
import django.utils.copycompat as copy
|
7 | 7 | from django import forms |
8 | 8 | from django.forms.widgets import RadioFieldRenderer |
9 | 9 | from django.forms.util import flatatt |
10 | | from django.utils.html import escape |
11 | | from django.utils.text import truncate_words |
12 | 10 | from django.utils.translation import ugettext as _ |
13 | 11 | from django.utils.safestring import mark_safe |
14 | 12 | from django.utils.encoding import force_unicode |
15 | 13 | from django.conf import settings |
16 | | from django.core.urlresolvers import reverse, NoReverseMatch |
| 14 | from django.contrib.admin.util import get_related_url, obj_label |
17 | 15 | |
18 | 16 | class FilteredSelectMultiple(forms.SelectMultiple): |
19 | 17 | """ |
… |
… |
class ForeignKeyRawIdWidget(forms.TextInput):
|
110 | 108 | def render(self, name, value, attrs=None): |
111 | 109 | if attrs is None: |
112 | 110 | attrs = {} |
113 | | related_url = '../../../%s/%s/' % (self.rel.to._meta.app_label, self.rel.to._meta.object_name.lower()) |
| 111 | # it would make sense to bind admin_site to ForeignKeyRawIdWidget as |
| 112 | # well (see RelatedFieldWidgetWrapper.__init__) for proper URL reversing |
| 113 | related_url = get_related_url(self.rel.to) |
114 | 114 | params = self.url_parameters() |
115 | 115 | if params: |
116 | 116 | url = '?' + '&'.join(['%s=%s' % (k, v) for k, v in params.items()]) |
… |
… |
class ForeignKeyRawIdWidget(forms.TextInput):
|
121 | 121 | output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)] |
122 | 122 | # TODO: "id_" is hard-coded here. This should instead use the correct |
123 | 123 | # API to determine the ID dynamically. |
124 | | output.append('<a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> ' % \ |
| 124 | output.append(' <a href="#" onclick="return clearRawId(this);"><img src="%(prefix)simg/admin/icon_deletelink.gif" width="10" height="10" alt="%(title)s" title="%(title)s" /></a>' % {'prefix': settings.ADMIN_MEDIA_PREFIX, 'title': _('Clear')}) |
| 125 | output.append(' <a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> ' % \ |
125 | 126 | (related_url, url, name)) |
126 | | output.append('<img src="%simg/admin/selector-search.gif" width="16" height="16" alt="%s" /></a>' % (settings.ADMIN_MEDIA_PREFIX, _('Lookup'))) |
127 | | if value: |
128 | | output.append(self.label_for_value(value)) |
| 127 | output.append('<img src="%(prefix)simg/admin/selector-search.gif" width="16" height="16" alt="%(title)s" title="%(title)s" /></a>' % {'prefix': settings.ADMIN_MEDIA_PREFIX, 'title': _('Lookup')}) |
| 128 | output.append(self.label_for_value(value, 'view_lookup_id_%s' % name)) |
129 | 129 | return mark_safe(u''.join(output)) |
130 | 130 | |
131 | 131 | def base_url_parameters(self): |
… |
… |
class ForeignKeyRawIdWidget(forms.TextInput):
|
147 | 147 | params.update({TO_FIELD_VAR: self.rel.get_related_field().name}) |
148 | 148 | return params |
149 | 149 | |
150 | | def label_for_value(self, value): |
151 | | key = self.rel.get_related_field().name |
152 | | obj = self.rel.to._default_manager.using(self.db).get(**{key: value}) |
153 | | return ' <strong>%s</strong>' % escape(truncate_words(obj, 14)) |
| 150 | def label_for_value(self, value, name): |
| 151 | if value: |
| 152 | key = self.rel.get_related_field().name |
| 153 | obj = self.rel.to._default_manager.using( |
| 154 | self.db).get(**{key: value}) |
| 155 | related_url = get_related_url(obj, obj.pk) |
| 156 | return (' <strong id="%s"><a href="%s" ' |
| 157 | 'onclick="return showRelatedObjectPopup(this);">%s</a>' |
| 158 | '</strong>' % (name, related_url, obj_label(obj))) |
| 159 | else: |
| 160 | # a placeholder that will be filled in |
| 161 | # JavaScript dismissRelatedLookupPopup() |
| 162 | return ' <strong id="%s"></strong>' % name |
154 | 163 | |
155 | 164 | class ManyToManyRawIdWidget(ForeignKeyRawIdWidget): |
156 | 165 | """ |
… |
… |
class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
|
171 | 180 | def url_parameters(self): |
172 | 181 | return self.base_url_parameters() |
173 | 182 | |
174 | | def label_for_value(self, value): |
| 183 | def label_for_value(self, value, name): |
175 | 184 | return '' |
176 | 185 | |
177 | 186 | def value_from_datadict(self, data, files, name): |
… |
… |
class RelatedFieldWidgetWrapper(forms.Widget):
|
221 | 230 | media = property(_media) |
222 | 231 | |
223 | 232 | def render(self, name, value, *args, **kwargs): |
224 | | rel_to = self.rel.to |
225 | | info = (rel_to._meta.app_label, rel_to._meta.object_name.lower()) |
226 | | try: |
227 | | related_url = reverse('admin:%s_%s_add' % info, current_app=self.admin_site.name) |
228 | | except NoReverseMatch: |
229 | | info = (self.admin_site.root_path, rel_to._meta.app_label, rel_to._meta.object_name.lower()) |
230 | | related_url = '%s%s/%s/add/' % info |
231 | 233 | self.widget.choices = self.choices |
232 | 234 | output = [self.widget.render(name, value, *args, **kwargs)] |
| 235 | rel_to = self.rel.to |
233 | 236 | if rel_to in self.admin_site._registry: # If the related object has an admin interface: |
| 237 | related_url = get_related_url(rel_to, 'add', self.admin_site) |
234 | 238 | # TODO: "id_" is hard-coded here. This should instead use the correct |
235 | 239 | # API to determine the ID dynamically. |
236 | 240 | output.append(u'<a href="%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> ' % \ |
diff --git a/tests/regressiontests/admin_widgets/models.py b/tests/regressiontests/admin_widgets/models.py
index b9fe67c..8f4f2b1 100644
a
|
b
|
from django.db import models
|
4 | 4 | from django.core.files.storage import default_storage |
5 | 5 | from django.contrib.auth.models import User |
6 | 6 | |
7 | | class MyFileField(models.FileField): |
8 | | pass |
| 7 | class MyFileField(models.FileField): |
| 8 | pass |
9 | 9 | |
10 | 10 | class Member(models.Model): |
11 | 11 | name = models.CharField(max_length=100) |
… |
… |
Currently: <a target="_blank" href="%(STORAGE_URL)salbums/hybrid_theory.jpg">alb
|
116 | 116 | >>> rel = Album._meta.get_field('band').rel |
117 | 117 | >>> w = ForeignKeyRawIdWidget(rel) |
118 | 118 | >>> print conditional_escape(w.render('test', band.pk, attrs={})) |
119 | | <input type="text" name="test" value="1" class="vForeignKeyRawIdAdminField" /><a href="../../../admin_widgets/band/?t=id" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a> <strong>Linkin Park</strong> |
| 119 | <input type="text" name="test" value="1" class="vForeignKeyRawIdAdminField" /> <a href="#" onclick="return clearRawId(this);"><img src="%(ADMIN_MEDIA_PREFIX)simg/admin/icon_deletelink.gif" width="10" height="10" alt="Clear" title="Clear" /></a> <a href="../../../admin_widgets/band/?t=id" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" title="Lookup" /></a> <strong id="view_lookup_id_test"><a href="../../../admin_widgets/band/1/" onclick="return showRelatedObjectPopup(this);">Linkin Park</a></strong> |
120 | 120 | |
121 | 121 | >>> m1 = Member.objects.create(pk=1, name='Chester') |
122 | 122 | >>> m2 = Member.objects.create(pk=2, name='Mike') |
… |
… |
Currently: <a target="_blank" href="%(STORAGE_URL)salbums/hybrid_theory.jpg">alb
|
125 | 125 | >>> rel = Band._meta.get_field('members').rel |
126 | 126 | >>> w = ManyToManyRawIdWidget(rel) |
127 | 127 | >>> print conditional_escape(w.render('test', [m1.pk, m2.pk], attrs={})) |
128 | | <input type="text" name="test" value="1,2" class="vManyToManyRawIdAdminField" /><a href="../../../admin_widgets/member/" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a> |
| 128 | ||| FIXME -- ManyToManyRawIdWidget has not been implemented ||| |
129 | 129 | >>> w._has_changed(None, None) |
130 | 130 | False |
131 | 131 | >>> w._has_changed([], None) |
… |
… |
True
|
147 | 147 | >>> rel = Inventory._meta.get_field('parent').rel |
148 | 148 | >>> w = ForeignKeyRawIdWidget(rel) |
149 | 149 | >>> print w.render('test', core.parent_id, attrs={}) |
150 | | <input type="text" name="test" value="86" class="vForeignKeyRawIdAdminField" /><a href="../../../admin_widgets/inventory/?t=barcode" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a> <strong>Apple</strong> |
| 150 | <input type="text" name="test" value="86" class="vForeignKeyRawIdAdminField" /> <a href="#" onclick="return clearRawId(this);"><img src="%(ADMIN_MEDIA_PREFIX)simg/admin/icon_deletelink.gif" width="10" height="10" alt="Clear" title="Clear" /></a> <a href="../../../admin_widgets/inventory/?t=barcode" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" title="Lookup" /></a> <strong id="view_lookup_id_test"><a href="../../../admin_widgets/inventory/1/" onclick="return showRelatedObjectPopup(this);">Apple</a></strong> |
151 | 151 | |
152 | 152 | # see #9258 |
153 | 153 | >>> hidden = Inventory.objects.create(barcode=93, name='Hidden', hidden=True) |
154 | 154 | >>> child_of_hidden = Inventory.objects.create(barcode=94, name='Child of hidden', parent=hidden) |
155 | 155 | >>> print w.render('test', child_of_hidden.parent_id, attrs={}) |
156 | | <input type="text" name="test" value="93" class="vForeignKeyRawIdAdminField" /><a href="../../../admin_widgets/inventory/?t=barcode" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a> <strong>Hidden</strong> |
| 156 | <input type="text" name="test" value="93" class="vForeignKeyRawIdAdminField" /> <a href="#" onclick="return clearRawId(this);"><img src="%(ADMIN_MEDIA_PREFIX)simg/admin/icon_deletelink.gif" width="10" height="10" alt="Clear" title="Clear" /></a> <a href="../../../admin_widgets/inventory/?t=barcode" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" title="Lookup" /></a> <strong id="view_lookup_id_test"><a href="../../../admin_widgets/inventory/4/" onclick="return showRelatedObjectPopup(this);">Hidden</a></strong> |
| 157 | |
| 158 | >>> apostrophe = Inventory.objects.create(barcode=88, name="'Apostrophe', and <javascript> and a really really` really really really really really long one!") |
| 159 | >>> apostrophic_child = Inventory.objects.create(barcode=89, name="Apostrophe's child", parent=apostrophe) |
| 160 | >>> print w.render('test', apostrophic_child.parent_id, attrs={}) |
| 161 | <input type="text" name="test" value="88" class="vForeignKeyRawIdAdminField" /> <a href="#" onclick="return clearRawId(this);"><img src="%(ADMIN_MEDIA_PREFIX)simg/admin/icon_deletelink.gif" width="10" height="10" alt="Clear" title="Clear" /></a> <a href="../../../admin_widgets/inventory/?t=barcode" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" title="Lookup" /></a> <strong id="view_lookup_id_test"><a href="../../../admin_widgets/inventory/6/" onclick="return showRelatedObjectPopup(this);">'Apostrophe', and <javascript> and a really really` ...</a></strong> |
157 | 162 | """ % { |
158 | 163 | 'ADMIN_MEDIA_PREFIX': settings.ADMIN_MEDIA_PREFIX, |
159 | 164 | 'STORAGE_URL': default_storage.url(''), |