diff options
| author | Derek Anderson <public@kered.org> | 2006-10-26 19:09:51 +0000 |
|---|---|---|
| committer | Derek Anderson <public@kered.org> | 2006-10-26 19:09:51 +0000 |
| commit | 42851d90dadbf62f5d342ce5c4f496ba1eeba987 (patch) | |
| tree | a5d0e5c178afb2d7dbb7bf5ab37db9ced42f4b52 /django/contrib/admin | |
| parent | 450889c9a6f7da3c2fce77a0ccf4c4cea9e29710 (diff) | |
committing to schema-evolution
merge from HEAD
git-svn-id: http://code.djangoproject.com/svn/django/branches/schema-evolution@3937 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/contrib/admin')
40 files changed, 320 insertions, 216 deletions
diff --git a/django/contrib/admin/filterspecs.py b/django/contrib/admin/filterspecs.py index 25376be12a..8c2b82147e 100644 --- a/django/contrib/admin/filterspecs.py +++ b/django/contrib/admin/filterspecs.py @@ -123,7 +123,7 @@ class DateFieldFilterSpec(FilterSpec): def choices(self, cl): for title, param_dict in self.links: yield {'selected': self.date_params == param_dict, - 'query_string': cl.get_query_string(param_dict, self.field_generic), + 'query_string': cl.get_query_string(param_dict, [self.field_generic]), 'display': title} FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec) diff --git a/django/contrib/admin/media/css/changelists.css b/django/contrib/admin/media/css/changelists.css index fbcbe56f06..4834be4685 100644 --- a/django/contrib/admin/media/css/changelists.css +++ b/django/contrib/admin/media/css/changelists.css @@ -42,9 +42,9 @@ /* PAGINATOR */ .paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; } -.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; } +.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; } .paginator a.showall { padding:0 !important; border:none !important; } .paginator a.showall:hover { color:#036 !important; background:transparent !important; } -.paginator .end { border-width:2px !important; margin-right:6px; } +.paginator .end { border-width:2px !important; margin-right:6px; } .paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; } .paginator a:hover { color:white; background:#5b80b2; border-color:#036; } diff --git a/django/contrib/admin/media/css/forms.css b/django/contrib/admin/media/css/forms.css index b66f268fec..468e06a8a2 100644 --- a/django/contrib/admin/media/css/forms.css +++ b/django/contrib/admin/media/css/forms.css @@ -7,10 +7,10 @@ form .form-row p { padding-left:0; font-size:11px; } /* FORM LABELS */ -form h4 { margin:0 !important; padding:0 !important; border:none !important; } +form h4 { margin:0 !important; padding:0 !important; border:none !important; } label { font-weight:normal !important; color:#666; font-size:12px; } label.inline { margin-left:20px; } -.required label, label.required { font-weight:bold !important; color:#333 !important; } +.required label, label.required { font-weight:bold !important; color:#333 !important; } /* RADIO BUTTONS */ form ul.radiolist li { list-style-type:none; } diff --git a/django/contrib/admin/media/css/global.css b/django/contrib/admin/media/css/global.css index a87931681c..d50601bde7 100644 --- a/django/contrib/admin/media/css/global.css +++ b/django/contrib/admin/media/css/global.css @@ -1,4 +1,4 @@ -body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; } +body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; } /* LINKS */ a:link, a:visited { color: #5b80b2; text-decoration:none; } @@ -31,7 +31,7 @@ fieldset { margin:0; padding:0; } blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; } code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; } pre.literal-block { margin:10px; background:#eee; padding:6px 8px; } -code strong { color:#930; } +code strong { color:#930; } hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; } /* TEXT STYLES & MODIFIERS */ @@ -81,7 +81,7 @@ table.orderable tbody tr td:first-child { padding-left:14px; background-image:ur table.orderable-initalized .order-cell, body>tr>td.order-cell { display:none; } /* FORM DEFAULTS */ -input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; } +input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; } textarea { vertical-align:top !important; } input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; } @@ -92,7 +92,7 @@ input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2 input[type=submit].default:active { background-image:url(../img/admin/default-bg-reverse.gif); background-position:top; } /* MODULES */ -.module { border:1px solid #ccc; margin-bottom:5px; background:white; } +.module { border:1px solid #ccc; margin-bottom:5px; background:white; } .module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; } .module blockquote { margin-left:12px; } .module ul, .module ol { margin-left:1.5em; } diff --git a/django/contrib/admin/media/css/layout.css b/django/contrib/admin/media/css/layout.css index befe4fc1ca..17c52861ee 100644 --- a/django/contrib/admin/media/css/layout.css +++ b/django/contrib/admin/media/css/layout.css @@ -4,7 +4,7 @@ #header { width:100%; } #content-main { float:left; width:100%; } #content-related { float:right; width:18em; position:relative; margin-right:-19em; } -#footer { clear:both; padding:10px; } +#footer { clear:both; padding:10px; } /* COLUMN TYPES */ .colMS { margin-right:20em !important; } @@ -16,14 +16,14 @@ .dashboard #content { width:500px; } /* HEADER */ -#header { background:#417690; color:#ffc; overflow:hidden; } +#header { background:#417690; color:#ffc; overflow:hidden; } #header a:link, #header a:visited { color:white; } #header a:hover { text-decoration:underline; } #branding h1 { padding:0 10px; font-size:18px; margin:8px 0; font-weight:normal; color:#f4f379; } #branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; } -#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; } +#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; } /* SIDEBAR */ #content-related h3 { font-size:12px; color:#666; margin-bottom:3px; } #content-related h4 { font-size:11px; } -#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
\ No newline at end of file +#content-related .module h2 { background:#eee url(../img/admin/nav-bg.gif) bottom left repeat-x; color:#666; }
\ No newline at end of file diff --git a/django/contrib/admin/media/css/rtl.css b/django/contrib/admin/media/css/rtl.css index c29391cabf..1974e7c2ec 100644 --- a/django/contrib/admin/media/css/rtl.css +++ b/django/contrib/admin/media/css/rtl.css @@ -16,7 +16,7 @@ th { text-align: right; } /* layout styles */ -#user-tools { right:auto; left:0; text-align:left; } +#user-tools { right:auto; left:0; text-align:left; } div.breadcrumbs { text-align:right; } #content-main { float:right;} #content-related { float:left; margin-left:-19em; margin-right:auto;} diff --git a/django/contrib/admin/media/js/admin/CollapsedFieldsets.js b/django/contrib/admin/media/js/admin/CollapsedFieldsets.js index 97f0a68d04..c8426db228 100644 --- a/django/contrib/admin/media/js/admin/CollapsedFieldsets.js +++ b/django/contrib/admin/media/js/admin/CollapsedFieldsets.js @@ -3,83 +3,83 @@ // link when the fieldset is visible. function findForm(node) { - // returns the node of the form containing the given node - if (node.tagName.toLowerCase() != 'form') { - return findForm(node.parentNode); - } - return node; + // returns the node of the form containing the given node + if (node.tagName.toLowerCase() != 'form') { + return findForm(node.parentNode); + } + return node; } var CollapsedFieldsets = { - collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with. - collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden. - collapsed_class: 'collapsed', - init: function() { - var fieldsets = document.getElementsByTagName('fieldset'); - var collapsed_seen = false; - for (var i = 0, fs; fs = fieldsets[i]; i++) { - // Collapse this fieldset if it has the correct class, and if it - // doesn't have any errors. (Collapsing shouldn't apply in the case - // of error messages.) - if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) { - collapsed_seen = true; - // Give it an additional class, used by CSS to hide it. - fs.className += ' ' + CollapsedFieldsets.collapsed_class; - // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>) - var collapse_link = document.createElement('a'); - collapse_link.className = 'collapse-toggle'; - collapse_link.id = 'fieldsetcollapser' + i; - collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;'); - collapse_link.href = '#'; - collapse_link.innerHTML = gettext('Show'); - var h2 = fs.getElementsByTagName('h2')[0]; - h2.appendChild(document.createTextNode(' (')); - h2.appendChild(collapse_link); - h2.appendChild(document.createTextNode(')')); - } - } - if (collapsed_seen) { - // Expand all collapsed fieldsets when form is submitted. - addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); }); - } - }, - fieldset_has_errors: function(fs) { - // Returns true if any fields in the fieldset have validation errors. - var divs = fs.getElementsByTagName('div'); - for (var i=0; i<divs.length; i++) { - if (divs[i].className.match(/\berror\b/)) { - return true; - } - } - return false; - }, - show: function(fieldset_index) { - var fs = document.getElementsByTagName('fieldset')[fieldset_index]; - // Remove the class name that causes the "display: none". - fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, ''); - // Toggle the "Show" link to a "Hide" link - var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index); - collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;'); - collapse_link.innerHTML = gettext('Hide'); - }, - hide: function(fieldset_index) { - var fs = document.getElementsByTagName('fieldset')[fieldset_index]; - // Add the class name that causes the "display: none". - fs.className += ' ' + CollapsedFieldsets.collapsed_class; - // Toggle the "Hide" link to a "Show" link - var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index); + collapse_re: /\bcollapse\b/, // Class of fieldsets that should be dealt with. + collapsed_re: /\bcollapsed\b/, // Class that fieldsets get when they're hidden. + collapsed_class: 'collapsed', + init: function() { + var fieldsets = document.getElementsByTagName('fieldset'); + var collapsed_seen = false; + for (var i = 0, fs; fs = fieldsets[i]; i++) { + // Collapse this fieldset if it has the correct class, and if it + // doesn't have any errors. (Collapsing shouldn't apply in the case + // of error messages.) + if (fs.className.match(CollapsedFieldsets.collapse_re) && !CollapsedFieldsets.fieldset_has_errors(fs)) { + collapsed_seen = true; + // Give it an additional class, used by CSS to hide it. + fs.className += ' ' + CollapsedFieldsets.collapsed_class; + // (<a id="fieldsetcollapser3" class="collapse-toggle" href="#">Show</a>) + var collapse_link = document.createElement('a'); + collapse_link.className = 'collapse-toggle'; + collapse_link.id = 'fieldsetcollapser' + i; + collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;'); + collapse_link.href = '#'; + collapse_link.innerHTML = gettext('Show'); + var h2 = fs.getElementsByTagName('h2')[0]; + h2.appendChild(document.createTextNode(' (')); + h2.appendChild(collapse_link); + h2.appendChild(document.createTextNode(')')); + } + } + if (collapsed_seen) { + // Expand all collapsed fieldsets when form is submitted. + addEvent(findForm(document.getElementsByTagName('fieldset')[0]), 'submit', function() { CollapsedFieldsets.uncollapse_all(); }); + } + }, + fieldset_has_errors: function(fs) { + // Returns true if any fields in the fieldset have validation errors. + var divs = fs.getElementsByTagName('div'); + for (var i=0; i<divs.length; i++) { + if (divs[i].className.match(/\berror\b/)) { + return true; + } + } + return false; + }, + show: function(fieldset_index) { + var fs = document.getElementsByTagName('fieldset')[fieldset_index]; + // Remove the class name that causes the "display: none". + fs.className = fs.className.replace(CollapsedFieldsets.collapsed_re, ''); + // Toggle the "Show" link to a "Hide" link + var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index); + collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;'); + collapse_link.innerHTML = gettext('Hide'); + }, + hide: function(fieldset_index) { + var fs = document.getElementsByTagName('fieldset')[fieldset_index]; + // Add the class name that causes the "display: none". + fs.className += ' ' + CollapsedFieldsets.collapsed_class; + // Toggle the "Hide" link to a "Show" link + var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index); collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;'); - collapse_link.innerHTML = gettext('Show'); - }, + collapse_link.innerHTML = gettext('Show'); + }, - uncollapse_all: function() { - var fieldsets = document.getElementsByTagName('fieldset'); - for (var i=0; i<fieldsets.length; i++) { - if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) { - CollapsedFieldsets.show(i); - } - } - } + uncollapse_all: function() { + var fieldsets = document.getElementsByTagName('fieldset'); + for (var i=0; i<fieldsets.length; i++) { + if (fieldsets[i].className.match(CollapsedFieldsets.collapsed_re)) { + CollapsedFieldsets.show(i); + } + } + } } addEvent(window, 'load', CollapsedFieldsets.init); diff --git a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js index 35199baf84..77c536b865 100644 --- a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js +++ b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js @@ -8,7 +8,9 @@ var DateTimeShortcuts = { clockInputs: [], calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled calendarDivName2: 'calendarin', // name of <div> that contains calendar + calendarLinkName: 'calendarlink',// name of the link that is used to toggle clockDivName: 'clockbox', // name of clock <div> that gets toggled + clockLinkName: 'clocklink', // name of the link that is used to toggle admin_media_prefix: '', init: function() { // Deduce admin_media_prefix by looking at the <script>s in the @@ -46,6 +48,7 @@ var DateTimeShortcuts = { now_link.appendChild(document.createTextNode(gettext('Now'))); var clock_link = document.createElement('a'); clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');'); + clock_link.id = DateTimeShortcuts.clockLinkName + num; quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock')); shortcuts_span.appendChild(document.createTextNode('\240')); shortcuts_span.appendChild(now_link); @@ -69,17 +72,6 @@ var DateTimeShortcuts = { var clock_box = document.createElement('div'); clock_box.style.display = 'none'; clock_box.style.position = 'absolute'; - if (getStyle(document.body,'direction')!='rtl') { - clock_box.style.left = findPosX(clock_link) + 17 + 'px'; - } - else { - // since style's width is in em, it'd be tough to calculate - // px value of it. let's use an estimated px for now - // TODO: IE returns wrong value for findPosX when in rtl mode - // (it returns as it was left aligned), needs to be fixed. - clock_box.style.left = findPosX(clock_link) - 110 + 'px'; - } - clock_box.style.top = findPosY(clock_link) - 30 + 'px'; clock_box.className = 'clockbox module'; clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num); document.body.appendChild(clock_box); @@ -98,7 +90,25 @@ var DateTimeShortcuts = { quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');'); }, openClock: function(num) { - document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'block'; + var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num) + var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num) + + // Recalculate the clockbox position + // is it left-to-right or right-to-left layout ? + if (getStyle(document.body,'direction')!='rtl') { + clock_box.style.left = findPosX(clock_link) + 17 + 'px'; + } + else { + // since style's width is in em, it'd be tough to calculate + // px value of it. let's use an estimated px for now + // TODO: IE returns wrong value for findPosX when in rtl mode + // (it returns as it was left aligned), needs to be fixed. + clock_box.style.left = findPosX(clock_link) - 110 + 'px'; + } + clock_box.style.top = findPosY(clock_link) - 30 + 'px'; + + // Show the clock box + clock_box.style.display = 'block'; addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; }); }, dismissClock: function(num) { @@ -123,6 +133,7 @@ var DateTimeShortcuts = { today_link.appendChild(document.createTextNode(gettext('Today'))); var cal_link = document.createElement('a'); cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');'); + cal_link.id = DateTimeShortcuts.calendarLinkName + num; quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar')); shortcuts_span.appendChild(document.createTextNode('\240')); shortcuts_span.appendChild(today_link); @@ -149,18 +160,6 @@ var DateTimeShortcuts = { var cal_box = document.createElement('div'); cal_box.style.display = 'none'; cal_box.style.position = 'absolute'; - // is it left-to-right or right-to-left layout ? - if (getStyle(document.body,'direction')!='rtl') { - cal_box.style.left = findPosX(cal_link) + 17 + 'px'; - } - else { - // since style's width is in em, it'd be tough to calculate - // px value of it. let's use an estimated px for now - // TODO: IE returns wrong value for findPosX when in rtl mode - // (it returns as it was left aligned), needs to be fixed. - cal_box.style.left = findPosX(cal_link) - 180 + 'px'; - } - cal_box.style.top = findPosY(cal_link) - 75 + 'px'; cal_box.className = 'calendarbox module'; cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num); document.body.appendChild(cal_box); @@ -172,7 +171,6 @@ var DateTimeShortcuts = { cal_nav_prev.className = 'calendarnav-previous'; var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');'); cal_nav_next.className = 'calendarnav-next'; - cal_box.appendChild(cal_nav); // main box var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num); @@ -195,7 +193,24 @@ var DateTimeShortcuts = { quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');'); }, openCalendar: function(num) { - document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'block'; + var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num) + var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num) + + // Recalculate the clockbox position + // is it left-to-right or right-to-left layout ? + if (getStyle(document.body,'direction')!='rtl') { + cal_box.style.left = findPosX(cal_link) + 17 + 'px'; + } + else { + // since style's width is in em, it'd be tough to calculate + // px value of it. let's use an estimated px for now + // TODO: IE returns wrong value for findPosX when in rtl mode + // (it returns as it was left aligned), needs to be fixed. + cal_box.style.left = findPosX(cal_link) - 180 + 'px'; + } + cal_box.style.top = findPosY(cal_link) - 75 + 'px'; + + cal_box.style.display = 'block'; addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; }); }, dismissCalendar: function(num) { diff --git a/django/contrib/admin/media/js/admin/RelatedObjectLookups.js b/django/contrib/admin/media/js/admin/RelatedObjectLookups.js index cf57fc4dfb..db4ed1a9d1 100644 --- a/django/contrib/admin/media/js/admin/RelatedObjectLookups.js +++ b/django/contrib/admin/media/js/admin/RelatedObjectLookups.js @@ -11,7 +11,7 @@ function showRelatedObjectLookupPopup(triggeringLink) { } else { href = triggeringLink.href + '?pop=1'; } - var win = window.open(href, name, 'height=500,width=740,resizable=yes,scrollbars=yes'); + var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); win.focus(); return false; } diff --git a/django/contrib/admin/templates/admin/auth/user/add_form.html b/django/contrib/admin/templates/admin/auth/user/add_form.html new file mode 100644 index 0000000000..139fa6a75e --- /dev/null +++ b/django/contrib/admin/templates/admin/auth/user/add_form.html @@ -0,0 +1,28 @@ +{% extends "admin/change_form.html" %} +{% load i18n %} + +{% block after_field_sets %} + +<p>{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}</p> + +<fieldset class="module aligned"> + +<div class="form-row"> + {{ form.username.html_error_list }} + <label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }} + <p class="help">{{ username_help_text }}</p> +</div> + +<div class="form-row"> + {{ form.password1.html_error_list }} + <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }} +</div> + +<div class="form-row"> + {{ form.password2.html_error_list }} + <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }} + <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p> +</div> + +</fieldset> +{% endblock %} diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html index 67fe27529c..b63604b268 100644 --- a/django/contrib/admin/templates/admin/base.html +++ b/django/contrib/admin/templates/admin/base.html @@ -6,6 +6,7 @@ {% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %} {% block extrastyle %}{% endblock %} {% block extrahead %}{% endblock %} +{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %} </head> {% load i18n %} @@ -20,13 +21,13 @@ <div id="branding"> {% block branding %}{% endblock %} </div> - {% if not user.is_anonymous %}{% if user.is_staff %} + {% if user.is_authenticated and user.is_staff %} <div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div> - {% endif %}{% endif %} + {% endif %} {% block nav-global %}{% endblock %} </div> <!-- END Header --> - {% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} › {{ title }}{% endif %}</div>{% endblock %} + {% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} › {{ title|escape }}{% endif %}</div>{% endblock %} {% endif %} {% if messages %} @@ -36,7 +37,7 @@ <!-- Content --> <div id="content" class="{% block coltype %}colM{% endblock %}"> {% block pretitle %}{% endblock %} - {% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %} + {% block content_title %}{% if title %}<h1>{{ title|escape }}</h1>{% endif %}{% endblock %} {% block content %}{{ content }}{% endblock %} {% block sidebar %}{% endblock %} <br class="clear" /> diff --git a/django/contrib/admin/templates/admin/base_site.html b/django/contrib/admin/templates/admin/base_site.html index b867bd29bd..2bc7310873 100644 --- a/django/contrib/admin/templates/admin/base_site.html +++ b/django/contrib/admin/templates/admin/base_site.html @@ -1,7 +1,7 @@ {% extends "admin/base.html" %} {% load i18n %} -{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %} +{% block title %}{{ title|escape }} | {% trans 'Django site admin' %}{% endblock %} {% block branding %} <h1 id="site-name">{% trans 'Django administration' %}</h1> diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html index fa04969f01..b1fdc5ebdb 100644 --- a/django/contrib/admin/templates/admin/change_form.html +++ b/django/contrib/admin/templates/admin/change_form.html @@ -11,8 +11,8 @@ {% block breadcrumbs %}{% if not is_popup %} <div class="breadcrumbs"> <a href="../../../">{% trans "Home" %}</a> › - <a href="../">{{ opts.verbose_name_plural|capfirst }}</a> › - {% if add %}{% trans "Add" %} {{ opts.verbose_name }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %} + <a href="../">{{ opts.verbose_name_plural|capfirst|escape }}</a> › + {% if add %}{% trans "Add" %} {{ opts.verbose_name|escape }}{% else %}{{ original|truncatewords:"18"|escape }}{% endif %} </div> {% endif %}{% endblock %} {% block content %}<div id="content-main"> @@ -21,7 +21,7 @@ {% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%} </ul> {% endif %}{% endif %} -<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post">{% block form_top %}{% endblock %} +<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %} <div> {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %} {% if opts.admin.save_on_top %}{% submit_row %}{% endif %} diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html index 5b54bfb8cc..bd2304bd52 100644 --- a/django/contrib/admin/templates/admin/change_list.html +++ b/django/contrib/admin/templates/admin/change_list.html @@ -3,12 +3,12 @@ {% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %} {% block bodyclass %}change-list{% endblock %} {% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / <a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %} -{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> › {{ cl.opts.verbose_name_plural|capfirst }}</div>{% endblock %}{% endif %} +{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> › {{ cl.opts.verbose_name_plural|capfirst|escape }}</div>{% endblock %}{% endif %} {% block coltype %}flex{% endblock %} {% block content %} <div id="content-main"> {% if has_add_permission %} -<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}</a></li></ul> +<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name|escape as name %}Add {{ name }}{% endblocktrans %}</a></li></ul> {% endif %} <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist"> {% block search %}{% search_form cl %}{% endblock %} diff --git a/django/contrib/admin/templates/admin/date_hierarchy.html b/django/contrib/admin/templates/admin/date_hierarchy.html index a53d810f93..d2d69616c7 100644 --- a/django/contrib/admin/templates/admin/date_hierarchy.html +++ b/django/contrib/admin/templates/admin/date_hierarchy.html @@ -1,10 +1,10 @@ {% if show %} <div class="xfull"> <ul class="toplinks"> -{% if back %}<li class="date-back"><a href="{{ back.link }}">‹ {{ back.title }}</a></li>{% endif %} +{% if back %}<li class="date-back"><a href="{{ back.link }}">‹ {{ back.title|escape }}</a></li>{% endif %} {% for choice in choices %} -<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title }}{% if choice.link %}</a>{% endif %}</li> +<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title|escape }}{% if choice.link %}</a>{% endif %}</li> {% endfor %} </ul><br class="clear" /> </div> -{% endif %}
\ No newline at end of file +{% endif %} diff --git a/django/contrib/admin/templates/admin/delete_confirmation.html b/django/contrib/admin/templates/admin/delete_confirmation.html index f907c18a16..3921ab69e3 100644 --- a/django/contrib/admin/templates/admin/delete_confirmation.html +++ b/django/contrib/admin/templates/admin/delete_confirmation.html @@ -4,21 +4,21 @@ {% block breadcrumbs %} <div class="breadcrumbs"> <a href="../../../../">{% trans "Home" %}</a> › - <a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> › - <a href="../">{{ object|striptags|truncatewords:"18" }}</a> › + <a href="../../">{{ opts.verbose_name_plural|capfirst|escape }}</a> › + <a href="../">{{ object|escape|truncatewords:"18" }}</a> › {% trans 'Delete' %} </div> {% endblock %} {% block content %} {% if perms_lacking %} - <p>{% blocktrans %}Deleting the {{ object_name }} '{{ object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p> + <p>{% blocktrans with object|escape as escaped_object %}Deleting the {{ object_name }} '{{ escaped_object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p> <ul> {% for obj in perms_lacking %} - <li>{{ obj }}</li> + <li>{{ obj|escape }}</li> {% endfor %} </ul> {% else %} - <p>{% blocktrans %}Are you sure you want to delete the {{ object_name }} "{{ object }}"? All of the following related items will be deleted:{% endblocktrans %}</p> + <p>{% blocktrans with object|escape as escaped_object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktrans %}</p> <ul>{{ deleted_objects|unordered_list }}</ul> <form action="" method="post"> <div> diff --git a/django/contrib/admin/templates/admin/edit_inline_stacked.html b/django/contrib/admin/templates/admin/edit_inline_stacked.html index 45aa0a4f58..48ecc698d9 100644 --- a/django/contrib/admin/templates/admin/edit_inline_stacked.html +++ b/django/contrib/admin/templates/admin/edit_inline_stacked.html @@ -1,7 +1,7 @@ {% load admin_modify %} <fieldset class="module aligned"> {% for fcw in bound_related_object.form_field_collection_wrappers %} - <h2>{{ bound_related_object.relation.opts.verbose_name|capfirst }} #{{ forloop.counter }}</h2> + <h2>{{ bound_related_object.relation.opts.verbose_name|capfirst|escape }} #{{ forloop.counter }}</h2> {% if bound_related_object.show_url %}{% if fcw.obj.original %} <p><a href="/r/{{ fcw.obj.original.content_type_id }}/{{ fcw.obj.original.id }}/">View on site</a></p> {% endif %}{% endif %} diff --git a/django/contrib/admin/templates/admin/edit_inline_tabular.html b/django/contrib/admin/templates/admin/edit_inline_tabular.html index e9535df02c..3d059c8b3d 100644 --- a/django/contrib/admin/templates/admin/edit_inline_tabular.html +++ b/django/contrib/admin/templates/admin/edit_inline_tabular.html @@ -1,12 +1,13 @@ {% load admin_modify %} <fieldset class="module"> - <h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}</h2><table> + <h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst|escape }}</h2><table> <thead><tr> {% for fw in bound_related_object.field_wrapper_list %} {% if fw.needs_header %} - <th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst }}</th> + <th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th> {% endif %} {% endfor %} + </tr></thead> {% for fcw in bound_related_object.form_field_collection_wrappers %} {% if change %}{% if original_row_needed %} {% if fcw.obj.original %} diff --git a/django/contrib/admin/templates/admin/filter.html b/django/contrib/admin/templates/admin/filter.html index 5b0e78b6fc..8b5b521437 100644 --- a/django/contrib/admin/templates/admin/filter.html +++ b/django/contrib/admin/templates/admin/filter.html @@ -1,5 +1,5 @@ {% load i18n %} -<h3>{% blocktrans %} By {{ title }} {% endblocktrans %}</h3> +<h3>{% blocktrans with title|escape as filter_title %} By {{ filter_title }} {% endblocktrans %}</h3> <ul> {% for choice in choices %} <li{% if choice.selected %} class="selected"{% endif %}> diff --git a/django/contrib/admin/templates/admin/index.html b/django/contrib/admin/templates/admin/index.html index f7b121723a..aa63c14fce 100644 --- a/django/contrib/admin/templates/admin/index.html +++ b/django/contrib/admin/templates/admin/index.html @@ -19,9 +19,9 @@ {% for model in app.models %} <tr> {% if model.perms.change %} - <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th> + <th scope="row"><a href="{{ model.admin_url }}">{{ model.name|escape }}</a></th> {% else %} - <th scope="row">{{ model.name }}</th> + <th scope="row">{{ model.name|escape }}</th> {% endif %} {% if model.perms.add %} @@ -58,7 +58,7 @@ {% else %} <ul class="actionlist"> {% for entry in admin_log %} - <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.content_type.name|capfirst }}</span></li> + <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr|escape }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{{ entry.content_type.name|capfirst|escape }}</span></li> {% endfor %} </ul> {% endif %} diff --git a/django/contrib/admin/templates/admin/invalid_setup.html b/django/contrib/admin/templates/admin/invalid_setup.html index 1fa0d32358..1d7d61f0d2 100644 --- a/django/contrib/admin/templates/admin/invalid_setup.html +++ b/django/contrib/admin/templates/admin/invalid_setup.html @@ -1,7 +1,7 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {{ title }}</div>{% endblock %} +{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans 'Home' %}</a> › {{ title|escape }}</div>{% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin/login.html b/django/contrib/admin/templates/admin/login.html index 5f338f703e..0773132cec 100644 --- a/django/contrib/admin/templates/admin/login.html +++ b/django/contrib/admin/templates/admin/login.html @@ -13,17 +13,17 @@ {% endif %} <div id="content-main"> <form action="{{ app_path }}" method="post" id="login-form"> - <div class="form-row"> - <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" /> - </div> - <div class="form-row"> - <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" /> - <input type="hidden" name="this_is_the_login_form" value="1" /> - <input type="hidden" name="post_data" value="{{ post_data }}" /> {% comment %}<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %} - </div> - <div class="submit-row"> - <label> </label><input type="submit" value="{% trans 'Log in' %}" /> - </div> + <div class="form-row"> + <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" /> + </div> + <div class="form-row"> + <label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" /> + <input type="hidden" name="this_is_the_login_form" value="1" /> + <input type="hidden" name="post_data" value="{{ post_data }}" /> {#<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>#} + </div> + <div class="submit-row"> + <label> </label><input type="submit" value="{% trans 'Log in' %}" /> + </div> </form> <script type="text/javascript"> diff --git a/django/contrib/admin/templates/admin/object_history.html b/django/contrib/admin/templates/admin/object_history.html index fc568305ca..14a77b8a31 100644 --- a/django/contrib/admin/templates/admin/object_history.html +++ b/django/contrib/admin/templates/admin/object_history.html @@ -2,7 +2,7 @@ {% load i18n %} {% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %} {% block breadcrumbs %} -<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> › <a href="../../">{{ module_name }}</a> › <a href="../">{{ object|truncatewords:"18" }}</a> › {% trans 'History' %}</div> +<div class="breadcrumbs"><a href="../../../../">{% trans 'Home' %}</a> › <a href="../../">{{ module_name|escape }}</a> › <a href="../">{{ object|escape|truncatewords:"18" }}</a> › {% trans 'History' %}</div> {% endblock %} {% block content %} diff --git a/django/contrib/admin/templates/admin/pagination.html b/django/contrib/admin/templates/admin/pagination.html index 7694e4c5b0..e1c09b2932 100644 --- a/django/contrib/admin/templates/admin/pagination.html +++ b/django/contrib/admin/templates/admin/pagination.html @@ -6,6 +6,6 @@ {% paginator_number cl i %} {% endfor %} {% endif %} -{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %} +{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name|escape }}{% else %}{{ cl.opts.verbose_name_plural|escape }}{% endifequal %} {% if show_all_url %} <a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %} </p> diff --git a/django/contrib/admin/templates/admin_doc/index.html b/django/contrib/admin/templates/admin_doc/index.html index 331774d2b3..74f9f20916 100644 --- a/django/contrib/admin/templates/admin_doc/index.html +++ b/django/contrib/admin/templates/admin_doc/index.html @@ -9,17 +9,17 @@ <h1>Documentation</h1>
<div id="content-main">
- <h3><a href="tags/">Tags</a></h3>
- <p>List of all the template tags and their functions.</p>
+ <h3><a href="tags/">Tags</a></h3>
+ <p>List of all the template tags and their functions.</p>
- <h3><a href="filters/">Filters</a></h3>
- <p>Filters are actions which can be applied to variables in a template to alter the output.</p>
+ <h3><a href="filters/">Filters</a></h3>
+ <p>Filters are actions which can be applied to variables in a template to alter the output.</p>
- <h3><a href="models/">Models</a></h3>
- <p>Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables.</p>
+ <h3><a href="models/">Models</a></h3>
+ <p>Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables.</p>
- <h3><a href="views/">Views</a></h3>
- <p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
+ <h3><a href="views/">Views</a></h3>
+ <p>Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.</p>
<h3><a href="bookmarklets/">Bookmarklets</a></h3>
<p>Tools for your browser to quickly access admin functionality.</p>
diff --git a/django/contrib/admin/templates/admin_doc/missing_docutils.html b/django/contrib/admin/templates/admin_doc/missing_docutils.html index d0b571f957..cdeab0cdd8 100644 --- a/django/contrib/admin/templates/admin_doc/missing_docutils.html +++ b/django/contrib/admin/templates/admin_doc/missing_docutils.html @@ -9,9 +9,9 @@ <h1>Documentation</h1> <div id="content-main"> - <h3>The admin documentation system requires Python's <a href="http://docutils.sf.net/">docutils</a> library.</h3> + <h3>The admin documentation system requires Python's <a href="http://docutils.sf.net/">docutils</a> library.</h3> - <p>Please ask your administrators to install <a href="http://docutils.sf.net/">docutils</a>.</p> + <p>Please ask your administrators to install <a href="http://docutils.sf.net/">docutils</a>.</p> </div> {% endblock %} diff --git a/django/contrib/admin/templates/admin_doc/model_detail.html b/django/contrib/admin/templates/admin_doc/model_detail.html index 9ac56864fa..70133e26dd 100644 --- a/django/contrib/admin/templates/admin_doc/model_detail.html +++ b/django/contrib/admin/templates/admin_doc/model_detail.html @@ -9,13 +9,13 @@ </style> {% endblock %} -{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Models</a> › {{ name }}</div>{% endblock %} +{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › <a href="../">Models</a> › {{ name|escape }}</div>{% endblock %} -{% block title %}Model: {{ name }}{% endblock %} +{% block title %}Model: {{ name|escape }}{% endblock %} {% block content %} <div id="content-main"> -<h1>{{ summary }}</h1> +<h1>{{ summary|escape }}</h1> {% if description %} <p>{% filter escape|linebreaksbr %}{% trans description %}{% endfilter %}</p> diff --git a/django/contrib/admin/templates/admin_doc/template_detail.html b/django/contrib/admin/templates/admin_doc/template_detail.html index df67f1856b..280ea912d0 100644 --- a/django/contrib/admin/templates/admin_doc/template_detail.html +++ b/django/contrib/admin/templates/admin_doc/template_detail.html @@ -1,19 +1,19 @@ {% extends "admin/base_site.html" %} {% load i18n %} -{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name }}</div>{% endblock %} +{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Home</a> › <a href="../../">Documentation</a> › Templates › {{ name|escape }}</div>{% endblock %} {% block userlinks %}<a href="../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../logout/">{% trans 'Log out' %}</a>{% endblock %} -{% block title %}Template: {{ name }}{% endblock %} +{% block title %}Template: {{ name|escape }}{% endblock %} {% block content %} -<h1>Template: "{{ name }}"</h1> +<h1>Template: "{{ name|escape }}"</h1> {% regroup templates|dictsort:"site_id" by site as templates_by_site %} {% for group in templates_by_site %} - <h2>Search path for template "{{ name }}" on {{ group.grouper }}:</h2> + <h2>Search path for template "{{ name|escape }}" on {{ group.grouper }}:</h2> <ol> {% for template in group.list|dictsort:"order" %} - <li><code>{{ template.file }}</code>{% if not template.exists %} <em>(does not exist)</em>{% endif %}</li> + <li><code>{{ template.file|escape }}</code>{% if not template.exists %} <em>(does not exist)</em>{% endif %}</li> {% endfor %} </ol> {% endfor %} diff --git a/django/contrib/admin/templates/widget/file.html b/django/contrib/admin/templates/widget/file.html index e4a0756211..e584abf956 100644 --- a/django/contrib/admin/templates/widget/file.html +++ b/django/contrib/admin/templates/widget/file.html @@ -1,4 +1,4 @@ {% load admin_modify i18n %}{% if bound_field.original_value %} -{% trans "Currently:" %} <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value }} </a><br /> +{% trans "Currently:" %} <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value|escape }} </a><br /> {% trans "Change:" %}{% output_all bound_field.form_fields %} {% else %} {% output_all bound_field.form_fields %} {% endif %} diff --git a/django/contrib/admin/templates/widget/foreign.html b/django/contrib/admin/templates/widget/foreign.html index 6b43d044bd..301f5214db 100644 --- a/django/contrib/admin/templates/widget/foreign.html +++ b/django/contrib/admin/templates/widget/foreign.html @@ -15,6 +15,6 @@ {{ bound_field.original_value }} {% endif %} {% if bound_field.raw_id_admin %} - {% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %} + {% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %} {% endif %} {% endif %} diff --git a/django/contrib/admin/templates/widget/one_to_one.html b/django/contrib/admin/templates/widget/one_to_one.html index a79a12314f..efd0117bf2 100644 --- a/django/contrib/admin/templates/widget/one_to_one.html +++ b/django/contrib/admin/templates/widget/one_to_one.html @@ -1,2 +1,2 @@ {% if add %}{% include "widget/foreign.html" %}{% endif %} -{% if change %}{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}{% endif %} +{% if change %}{% if bound_field.existing_display %} <strong>{{ bound_field.existing_display|truncatewords:"14"|escape }}</strong>{% endif %}{% endif %} diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 3537f46755..832b3562cd 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -1,8 +1,6 @@ -from django import template from django.conf import settings -from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, ALL_VAR +from django.contrib.admin.views.main import ALL_VAR, EMPTY_CHANGELIST_VALUE from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR -from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.utils import dateformat @@ -119,7 +117,7 @@ def items_for_result(cl, result): if callable(attr): attr = attr() result_repr = str(attr) - except AttributeError, ObjectDoesNotExist: + except (AttributeError, ObjectDoesNotExist): result_repr = EMPTY_CHANGELIST_VALUE else: # Strip HTML tags in the resulting text, except if the @@ -167,11 +165,12 @@ def items_for_result(cl, result): result_repr = ' ' # If list_display_links not defined, add the link tag to the first field if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links: + table_tag = {True:'th', False:'td'}[first] first = False url = cl.url_for_result(result) result_id = str(getattr(result, pk)) # str() is needed in case of 23L (long ints) - yield ('<th%s><a href="%s"%s>%s</a></th>' % \ - (row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr)) + yield ('<%s%s><a href="%s"%s>%s</a></%s>' % \ + (table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag)) else: yield ('<td%s>%s</td>' % (row_class, result_repr)) diff --git a/django/contrib/admin/templatetags/admin_modify.py b/django/contrib/admin/templatetags/admin_modify.py index 2d34452f52..d09fa28b10 100644 --- a/django/contrib/admin/templatetags/admin_modify.py +++ b/django/contrib/admin/templatetags/admin_modify.py @@ -1,9 +1,7 @@ from django import template from django.contrib.admin.views.main import AdminBoundField from django.template import loader -from django.utils.html import escape from django.utils.text import capfirst -from django.utils.functional import curry from django.db import models from django.db.models.fields import Field from django.db.models.related import BoundRelatedObject @@ -162,8 +160,10 @@ class EditInlineNode(template.Node): context.push() if relation.field.rel.edit_inline == models.TABULAR: bound_related_object_class = TabularBoundRelatedObject - else: + elif relation.field.rel.edit_inline == models.STACKED: bound_related_object_class = StackedBoundRelatedObject + else: + bound_related_object_class = relation.field.rel.edit_inline original = context.get('original', None) bound_related_object = relation.bind(context['form'], original, bound_related_object_class) context['bound_related_object'] = bound_related_object @@ -198,7 +198,7 @@ def filter_interface_script_maybe(bound_field): if f.rel and isinstance(f.rel, models.ManyToManyRel) and f.rel.filter_interface: return '<script type="text/javascript">addEvent(window, "load", function(e) {' \ ' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % ( - f.name, f.verbose_name, f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX) + f.name, f.verbose_name.replace('"', '\\"'), f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX) else: return '' filter_interface_script_maybe = register.simple_tag(filter_interface_script_maybe) diff --git a/django/contrib/admin/urls.py b/django/contrib/admin/urls.py index bd894d8de1..aaf9841e45 100644 --- a/django/contrib/admin/urls.py +++ b/django/contrib/admin/urls.py @@ -21,13 +21,15 @@ urlpatterns = patterns('', ('^doc/tags/$', 'django.contrib.admin.views.doc.template_tag_index'), ('^doc/filters/$', 'django.contrib.admin.views.doc.template_filter_index'), ('^doc/views/$', 'django.contrib.admin.views.doc.view_index'), - ('^doc/views/jump/$', 'django.contrib.admin.views.doc.jump_to_view'), ('^doc/views/(?P<view>[^/]+)/$', 'django.contrib.admin.views.doc.view_detail'), ('^doc/models/$', 'django.contrib.admin.views.doc.model_index'), ('^doc/models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$', 'django.contrib.admin.views.doc.model_detail'), # ('^doc/templates/$', 'django.views.admin.doc.template_index'), ('^doc/templates/(?P<template>.*)/$', 'django.contrib.admin.views.doc.template_detail'), + # "Add user" -- a special-case view + ('^auth/user/add/$', 'django.contrib.admin.views.auth.user_add_stage'), + # Add/change/delete/history ('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'), ('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'), diff --git a/django/contrib/admin/utils.py b/django/contrib/admin/utils.py index 0242b2f32e..9adf09b6a5 100644 --- a/django/contrib/admin/utils.py +++ b/django/contrib/admin/utils.py @@ -3,7 +3,6 @@ import re from email.Parser import HeaderParser from email.Errors import HeaderParseError -from urlparse import urljoin try: import docutils.core import docutils.nodes diff --git a/django/contrib/admin/views/auth.py b/django/contrib/admin/views/auth.py new file mode 100644 index 0000000000..03876bb4ac --- /dev/null +++ b/django/contrib/admin/views/auth.py @@ -0,0 +1,44 @@ +from django.contrib.admin.views.decorators import staff_member_required +from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth.models import User +from django.core.exceptions import PermissionDenied +from django import forms, template +from django.shortcuts import render_to_response +from django.http import HttpResponseRedirect + +def user_add_stage(request): + if not request.user.has_perm('auth.change_user'): + raise PermissionDenied + manipulator = UserCreationForm() + if request.method == 'POST': + new_data = request.POST.copy() + errors = manipulator.get_validation_errors(new_data) + if not errors: + new_user = manipulator.save(new_data) + msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user} + if request.POST.has_key("_addanother"): + request.user.message_set.create(message=msg) + return HttpResponseRedirect(request.path) + else: + request.user.message_set.create(message=msg + ' ' + _("You may edit it again below.")) + return HttpResponseRedirect('../%s/' % new_user.id) + else: + errors = new_data = {} + form = forms.FormWrapper(manipulator, new_data, errors) + return render_to_response('admin/auth/user/add_form.html', { + 'title': _('Add user'), + 'form': form, + 'is_popup': request.REQUEST.has_key('_popup'), + 'add': True, + 'change': False, + 'has_delete_permission': False, + 'has_change_permission': True, + 'has_file_field': False, + 'has_absolute_url': False, + 'auto_populated_fields': (), + 'bound_field_sets': (), + 'first_form_field_id': 'id_username', + 'opts': User._meta, + 'username_help_text': User._meta.get_field('username').help_text, + }, context_instance=template.RequestContext(request)) +user_add_stage = staff_member_required(user_add_stage) diff --git a/django/contrib/admin/views/decorators.py b/django/contrib/admin/views/decorators.py index 250c585220..9dfe651fe6 100644 --- a/django/contrib/admin/views/decorators.py +++ b/django/contrib/admin/views/decorators.py @@ -46,7 +46,7 @@ def staff_member_required(view_func): member, displaying the login page if necessary. """ def _checklogin(request, *args, **kwargs): - if not request.user.is_anonymous() and request.user.is_staff: + if request.user.is_authenticated() and request.user.is_staff: # The user is valid. Continue to the admin page. if request.POST.has_key('post_data'): # User must have re-authenticated through a different window @@ -87,7 +87,7 @@ def staff_member_required(view_func): # The user data is correct; log in the user in and continue. else: - if user.is_staff: + if user.is_active and user.is_staff: login(request, user) # TODO: set last_login with an event. user.last_login = datetime.datetime.now() diff --git a/django/contrib/admin/views/doc.py b/django/contrib/admin/views/doc.py index 5aa143e1fd..435d76f276 100644 --- a/django/contrib/admin/views/doc.py +++ b/django/contrib/admin/views/doc.py @@ -28,7 +28,7 @@ def bookmarklets(request): # Hack! This couples this view to the URL it lives at. admin_root = request.path[:-len('doc/bookmarklets/')] return render_to_response('admin_doc/bookmarklets.html', { - 'admin_url': "%s://%s%s" % (os.environ.get('HTTPS') == 'on' and 'https' or 'http', get_host(request), admin_root), + 'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', get_host(request), admin_root), }, context_instance=RequestContext(request)) bookmarklets = staff_member_required(bookmarklets) @@ -43,11 +43,11 @@ def template_tag_index(request): for tag_name, tag_func in library.tags.items(): title, body, metadata = utils.parse_docstring(tag_func.__doc__) if title: - title = utils.parse_rst(title, 'tag', 'tag:' + tag_name) + title = utils.parse_rst(title, 'tag', _('tag:') + tag_name) if body: - body = utils.parse_rst(body, 'tag', 'tag:' + tag_name) + body = utils.parse_rst(body, 'tag', _('tag:') + tag_name) for key in metadata: - metadata[key] = utils.parse_rst(metadata[key], 'tag', 'tag:' + tag_name) + metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name) if library in template.builtins: tag_library = None else: @@ -74,11 +74,11 @@ def template_filter_index(request): for filter_name, filter_func in library.filters.items(): title, body, metadata = utils.parse_docstring(filter_func.__doc__) if title: - title = utils.parse_rst(title, 'filter', 'filter:' + filter_name) + title = utils.parse_rst(title, 'filter', _('filter:') + filter_name) if body: - body = utils.parse_rst(body, 'filter', 'filter:' + filter_name) + body = utils.parse_rst(body, 'filter', _('filter:') + filter_name) for key in metadata: - metadata[key] = utils.parse_rst(metadata[key], 'filter', 'filter:' + filter_name) + metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name) if library in template.builtins: tag_library = None else: @@ -132,11 +132,11 @@ def view_detail(request, view): raise Http404 title, body, metadata = utils.parse_docstring(view_func.__doc__) if title: - title = utils.parse_rst(title, 'view', 'view:' + view) + title = utils.parse_rst(title, 'view', _('view:') + view) if body: - body = utils.parse_rst(body, 'view', 'view:' + view) + body = utils.parse_rst(body, 'view', _('view:') + view) for key in metadata: - metadata[key] = utils.parse_rst(metadata[key], 'model', 'view:' + view) + metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view) return render_to_response('admin_doc/view_detail.html', { 'name': view, 'summary': title, @@ -161,14 +161,14 @@ def model_detail(request, app_label, model_name): try: app_mod = models.get_app(app_label) except ImproperlyConfigured: - raise Http404, "App %r not found" % app_label + raise Http404, _("App %r not found") % app_label model = None for m in models.get_models(app_mod): if m._meta.object_name.lower() == model_name: model = m break if model is None: - raise Http404, "Model %r not found in app %r" % (model_name, app_label) + raise Http404, _("Model %r not found in app %r") % (model_name, app_label) opts = model._meta @@ -180,7 +180,7 @@ def model_detail(request, app_label, model_name): if isinstance(field, models.ForeignKey): data_type = related_object_name = field.rel.to.__name__ app_label = field.rel.to._meta.app_label - verbose = utils.parse_rst(("the related `%s.%s` object" % (app_label, data_type)), 'model', 'model:' + data_type) + verbose = utils.parse_rst((_("the related `%s.%s` object") % (app_label, data_type)), 'model', _('model:') + data_type) else: data_type = get_readable_field_data_type(field) verbose = field.verbose_name @@ -202,7 +202,7 @@ def model_detail(request, app_label, model_name): continue verbose = func.__doc__ if verbose: - verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', 'model:' + opts.module_name) + verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.module_name) fields.append({ 'name': func_name, 'data_type': get_return_data_type(func_name), @@ -211,22 +211,22 @@ def model_detail(request, app_label, model_name): # Gather related objects for rel in opts.get_all_related_objects(): - verbose = "related `%s.%s` objects" % (rel.opts.app_label, rel.opts.object_name) + verbose = _("related `%s.%s` objects") % (rel.opts.app_label, rel.opts.object_name) accessor = rel.get_accessor_name() fields.append({ 'name' : "%s.all" % accessor, 'data_type' : 'List', - 'verbose' : utils.parse_rst("all " + verbose , 'model', 'model:' + opts.module_name), + 'verbose' : utils.parse_rst(_("all %s") % verbose , 'model', _('model:') + opts.module_name), }) fields.append({ 'name' : "%s.count" % accessor, 'data_type' : 'Integer', - 'verbose' : utils.parse_rst("number of " + verbose , 'model', 'model:' + opts.module_name), + 'verbose' : utils.parse_rst(_("number of %s") % verbose , 'model', _('model:') + opts.module_name), }) return render_to_response('admin_doc/model_detail.html', { 'name': '%s.%s' % (opts.app_label, opts.object_name), - 'summary': "Fields on %s objects" % opts.object_name, + 'summary': _("Fields on %s objects") % opts.object_name, 'description': model.__doc__, 'fields': fields, }, context_instance=RequestContext(request)) @@ -328,15 +328,19 @@ def extract_views_from_urlpatterns(urlpatterns, base=''): """ views = [] for p in urlpatterns: - if hasattr(p, 'get_callback'): + if hasattr(p, '_get_callback'): try: - views.append((p.get_callback(), base + p.regex.pattern)) + views.append((p._get_callback(), base + p.regex.pattern)) except ViewDoesNotExist: continue elif hasattr(p, '_get_url_patterns'): - views.extend(extract_views_from_urlpatterns(p.url_patterns, base + p.regex.pattern)) + try: + patterns = p.url_patterns + except ImportError: + continue + views.extend(extract_views_from_urlpatterns(patterns, base + p.regex.pattern)) else: - raise TypeError, "%s does not appear to be a urlpattern object" % p + raise TypeError, _("%s does not appear to be a urlpattern object") % p return views named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)') diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index a7ee08f1c0..324841a669 100644 --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -10,9 +10,6 @@ from django.shortcuts import get_object_or_404, render_to_response from django.db import models from django.db.models.query import handle_legacy_orderlist, QuerySet from django.http import Http404, HttpResponse, HttpResponseRedirect -from django.template import loader -from django.utils import dateformat -from django.utils.dates import MONTHS from django.utils.html import escape from django.utils.text import capfirst, get_text_list import operator @@ -266,6 +263,8 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po post_url_continue += "?_popup=1" return HttpResponseRedirect(post_url_continue % pk_value) if request.POST.has_key("_popup"): + if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable. + pk_value = '"%s"' % pk_value.replace('"', '\\"') return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \ (pk_value, str(new_object).replace('"', '\\"'))) elif request.POST.has_key("_addanother"): @@ -455,7 +454,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current if related.opts.admin and has_related_objs: p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission()) if not user.has_perm(p): - perms_needed.add(rel_opts_name) + perms_needed.add(related.opts.verbose_name) for related in opts.get_all_related_many_to_many_objects(): if related.opts in opts_seen: continue @@ -714,10 +713,22 @@ class ChangeList(object): qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field) # Apply keyword searches. + def construct_search(field_name): + if field_name.startswith('^'): + return "%s__istartswith" % field_name[1:] + elif field_name.startswith('='): + return "%s__iexact" % field_name[1:] + elif field_name.startswith('@'): + return "%s__search" % field_name[1:] + else: + return "%s__icontains" % field_name + if self.lookup_opts.admin.search_fields and self.query: for bit in self.query.split(): - or_queries = [models.Q(**{'%s__icontains' % field_name: bit}) for field_name in self.lookup_opts.admin.search_fields] + or_queries = [models.Q(**{construct_search(field_name): bit}) for field_name in self.lookup_opts.admin.search_fields] other_qs = QuerySet(self.model) + if qs._select_related: + other_qs = other_qs.select_related() other_qs = other_qs.filter(reduce(operator.or_, or_queries)) qs = qs & other_qs diff --git a/django/contrib/admin/views/template.py b/django/contrib/admin/views/template.py index f73b9e4218..1684870842 100644 --- a/django/contrib/admin/views/template.py +++ b/django/contrib/admin/views/template.py @@ -22,7 +22,7 @@ def template_validator(request): new_data = request.POST.copy() errors = manipulator.get_validation_errors(new_data) if not errors: - request.user.add_message('The template is valid.') + request.user.message_set.create(message='The template is valid.') return render_to_response('admin/template_validator.html', { 'title': 'Template validator', 'form': forms.FormWrapper(manipulator, new_data, errors), @@ -32,7 +32,7 @@ template_validator = staff_member_required(template_validator) class TemplateValidator(forms.Manipulator): def __init__(self, settings_modules): self.settings_modules = settings_modules - site_list = Site.objects.get_in_bulk(settings_modules.keys()).values() + site_list = Site.objects.in_bulk(settings_modules.keys()).values() self.fields = ( forms.SelectField('site', is_required=True, choices=[(s.id, s.name) for s in site_list]), forms.LargeTextField('template', is_required=True, rows=25, validator_list=[self.isValidTemplate]), |
