diff options
Diffstat (limited to 'django/contrib/admin')
-rw-r--r-- | django/contrib/admin/filterspecs.py | 59 | ||||
-rw-r--r-- | django/contrib/admin/media/css/rtl.css | 46 | ||||
-rw-r--r-- | django/contrib/admin/media/js/admin/CollapsedFieldsets.js | 8 | ||||
-rw-r--r-- | django/contrib/admin/media/js/admin/DateTimeShortcuts.js | 23 | ||||
-rw-r--r-- | django/contrib/admin/media/js/core.js | 19 | ||||
-rw-r--r-- | django/contrib/admin/templates/admin/base.html | 5 | ||||
-rw-r--r-- | django/contrib/admin/templates/admin/filters.html | 3 | ||||
-rw-r--r-- | django/contrib/admin/templates/admin/pagination.html | 3 | ||||
-rw-r--r-- | django/contrib/admin/templates/admin/search_form.html | 2 | ||||
-rw-r--r-- | django/contrib/admin/templates/registration/password_reset_email.html | 2 | ||||
-rw-r--r-- | django/contrib/admin/templatetags/admin_list.py | 2 | ||||
-rw-r--r-- | django/contrib/admin/templatetags/admin_modify.py | 13 | ||||
-rw-r--r-- | django/contrib/admin/views/main.py | 2 |
13 files changed, 154 insertions, 33 deletions
diff --git a/django/contrib/admin/filterspecs.py b/django/contrib/admin/filterspecs.py index 0284f13114..25376be12a 100644 --- a/django/contrib/admin/filterspecs.py +++ b/django/contrib/admin/filterspecs.py @@ -11,18 +11,18 @@ import datetime class FilterSpec(object): filter_specs = [] - def __init__(self, f, request, params): + def __init__(self, f, request, params, model): self.field = f self.params = params def register(cls, test, factory): - cls.filter_specs.append( (test, factory) ) + cls.filter_specs.append((test, factory)) register = classmethod(register) - def create(cls, f, request, params): + def create(cls, f, request, params, model): for test, factory in cls.filter_specs: if test(f): - return factory(f, request, params) + return factory(f, request, params, model) create = classmethod(create) def has_output(self): @@ -48,8 +48,8 @@ class FilterSpec(object): return "".join(t) class RelatedFilterSpec(FilterSpec): - def __init__(self, f, request, params): - super(RelatedFilterSpec, self).__init__(f, request, params) + def __init__(self, f, request, params, model): + super(RelatedFilterSpec, self).__init__(f, request, params, model) if isinstance(f, models.ManyToManyField): self.lookup_title = f.rel.to._meta.verbose_name else: @@ -71,31 +71,31 @@ class RelatedFilterSpec(FilterSpec): for val in self.lookup_choices: pk_val = getattr(val, self.field.rel.to._meta.pk.attname) yield {'selected': self.lookup_val == str(pk_val), - 'query_string': cl.get_query_string( {self.lookup_kwarg: pk_val}), + 'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}), 'display': val} FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec) class ChoicesFilterSpec(FilterSpec): - def __init__(self, f, request, params): - super(ChoicesFilterSpec, self).__init__(f, request, params) + def __init__(self, f, request, params, model): + super(ChoicesFilterSpec, self).__init__(f, request, params, model) self.lookup_kwarg = '%s__exact' % f.name self.lookup_val = request.GET.get(self.lookup_kwarg, None) def choices(self, cl): yield {'selected': self.lookup_val is None, - 'query_string': cl.get_query_string( {}, [self.lookup_kwarg]), + 'query_string': cl.get_query_string({}, [self.lookup_kwarg]), 'display': _('All')} for k, v in self.field.choices: yield {'selected': str(k) == self.lookup_val, - 'query_string': cl.get_query_string( {self.lookup_kwarg: k}), + 'query_string': cl.get_query_string({self.lookup_kwarg: k}), 'display': v} FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec) class DateFieldFilterSpec(FilterSpec): - def __init__(self, f, request, params): - super(DateFieldFilterSpec, self).__init__(f, request, params) + def __init__(self, f, request, params, model): + super(DateFieldFilterSpec, self).__init__(f, request, params, model) self.field_generic = '%s__' % self.field.name @@ -123,14 +123,14 @@ 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) class BooleanFieldFilterSpec(FilterSpec): - def __init__(self, f, request, params): - super(BooleanFieldFilterSpec, self).__init__(f, request, params) + def __init__(self, f, request, params, model): + super(BooleanFieldFilterSpec, self).__init__(f, request, params, model) self.lookup_kwarg = '%s__exact' % f.name self.lookup_kwarg2 = '%s__isnull' % f.name self.lookup_val = request.GET.get(self.lookup_kwarg, None) @@ -142,11 +142,34 @@ class BooleanFieldFilterSpec(FilterSpec): def choices(self, cl): for k, v in ((_('All'), None), (_('Yes'), '1'), (_('No'), '0')): yield {'selected': self.lookup_val == v and not self.lookup_val2, - 'query_string': cl.get_query_string( {self.lookup_kwarg: v}, [self.lookup_kwarg2]), + 'query_string': cl.get_query_string({self.lookup_kwarg: v}, [self.lookup_kwarg2]), 'display': k} if isinstance(self.field, models.NullBooleanField): yield {'selected': self.lookup_val2 == 'True', - 'query_string': cl.get_query_string( {self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]), + 'query_string': cl.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]), 'display': _('Unknown')} FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec) + +# This should be registered last, because it's a last resort. For example, +# if a field is eligible to use the BooleanFieldFilterSpec, that'd be much +# more appropriate, and the AllValuesFilterSpec won't get used for it. +class AllValuesFilterSpec(FilterSpec): + def __init__(self, f, request, params, model): + super(AllValuesFilterSpec, self).__init__(f, request, params, model) + self.lookup_val = request.GET.get(f.name, None) + self.lookup_choices = model._meta.admin.manager.distinct().order_by(f.name).values(f.name) + + def title(self): + return self.field.verbose_name + + def choices(self, cl): + yield {'selected': self.lookup_val is None, + 'query_string': cl.get_query_string({}, [self.field.name]), + 'display': _('All')} + for val in self.lookup_choices: + val = str(val[self.field.name]) + yield {'selected': self.lookup_val == val, + 'query_string': cl.get_query_string({self.field.name: val}), + 'display': val} +FilterSpec.register(lambda f: True, AllValuesFilterSpec) diff --git a/django/contrib/admin/media/css/rtl.css b/django/contrib/admin/media/css/rtl.css new file mode 100644 index 0000000000..c29391cabf --- /dev/null +++ b/django/contrib/admin/media/css/rtl.css @@ -0,0 +1,46 @@ +body { direction: rtl; } + +/* login styles */ + +.login .form-row { float:right; } +.login .form-row label { float:right; padding-left:0.5em; padding-right:0; text-align:left;} +.login .submit-row { clear:both; padding:1em 9.4em 0 0; } + + +/* global styles */ +th { text-align: right; } +.module h2, .module caption { text-align: right; } +.addlink, .changelink { padding-left:0px; padding-right:12px; background-position:100% 0.2em; } +.deletelink { padding-left:0px; padding-right:12px; background-position:100% 0.25em; } +.object-tools { float:left; } + + +/* layout styles */ +#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;} +.colMS { margin-left:20em !important; margin-right:10px !important;} + +/* dashboard styles */ +.dashboard .module table td a { padding-left:.6em; padding-right:12px; } + +/* changelists styles */ +.change-list .filtered { background:white url(../img/admin/changelist-bg_rtl.gif) top left repeat-y !important; } +.change-list .filtered table { border-left:1px solid #ddd; border-right:0px none; } +#changelist-filter { right:auto; left:0; border-left:0px none; border-right:1px solid #ddd;} +.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { margin-right:0px !important; margin-left:160px !important; } +#changelist-filter li.selected { border-left:0px none; padding-left:0px; margin-left:0; border-right:5px solid #ccc; padding-right:5px;margin-right:-10px; } + +/* fomrs styles */ +.aligned label { padding:0 0 3px 1em; float:right; } +.submit-row { text-align: left } +.vDateField, .vTimeField { margin-left:2px; } + +/* widget styles */ +.calendarnav-previous { top:0; left:auto; right:0; } +.calendarnav-next { top:0; right:auto; left:0;} +.calendar caption, .calendarbox h2 { text-align:center; } + +.selector { float: right;} +.selector .selector-filter { text-align: right;} diff --git a/django/contrib/admin/media/js/admin/CollapsedFieldsets.js b/django/contrib/admin/media/js/admin/CollapsedFieldsets.js index 0b3ad9e421..97f0a68d04 100644 --- a/django/contrib/admin/media/js/admin/CollapsedFieldsets.js +++ b/django/contrib/admin/media/js/admin/CollapsedFieldsets.js @@ -31,7 +31,7 @@ var CollapsedFieldsets = { collapse_link.id = 'fieldsetcollapser' + i; collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;'); collapse_link.href = '#'; - collapse_link.innerHTML = 'Show'; + collapse_link.innerHTML = gettext('Show'); var h2 = fs.getElementsByTagName('h2')[0]; h2.appendChild(document.createTextNode(' (')); h2.appendChild(collapse_link); @@ -60,7 +60,7 @@ var CollapsedFieldsets = { // 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 = 'Hide'; + collapse_link.innerHTML = gettext('Hide'); }, hide: function(fieldset_index) { var fs = document.getElementsByTagName('fieldset')[fieldset_index]; @@ -69,9 +69,9 @@ var CollapsedFieldsets = { // 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 = 'Show'; + collapse_link.innerHTML = gettext('Show'); }, - + uncollapse_all: function() { var fieldsets = document.getElementsByTagName('fieldset'); for (var i=0; i<fieldsets.length; i++) { diff --git a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js index 28511f76c6..ed99c6103d 100644 --- a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js +++ b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js @@ -69,7 +69,16 @@ var DateTimeShortcuts = { var clock_box = document.createElement('div'); clock_box.style.display = 'none'; clock_box.style.position = 'absolute'; - clock_box.style.left = findPosX(clock_link) + 17 + 'px'; + 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); @@ -140,7 +149,17 @@ var DateTimeShortcuts = { var cal_box = document.createElement('div'); cal_box.style.display = 'none'; cal_box.style.position = 'absolute'; - cal_box.style.left = findPosX(cal_link) + 17 + 'px'; + // 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); diff --git a/django/contrib/admin/media/js/core.js b/django/contrib/admin/media/js/core.js index 1c8f678773..8eba69c9bb 100644 --- a/django/contrib/admin/media/js/core.js +++ b/django/contrib/admin/media/js/core.js @@ -135,4 +135,21 @@ String.prototype.pad_left = function(pad_length, pad_string) { new_string = pad_string + new_string; } return new_string; -}
\ No newline at end of file +} + +// ---------------------------------------------------------------------------- +// Get the computed style for and element +// ---------------------------------------------------------------------------- +function getStyle(oElm, strCssRule){ + var strValue = ""; + if(document.defaultView && document.defaultView.getComputedStyle){ + strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule); + } + else if(oElm.currentStyle){ + strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){ + return p1.toUpperCase(); + }); + strValue = oElm.currentStyle[strCssRule]; + } + return strValue; +} diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html index a8c1c9c101..e7f1c7e5a9 100644 --- a/django/contrib/admin/templates/admin/base.html +++ b/django/contrib/admin/templates/admin/base.html @@ -1,8 +1,9 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE }}" xml:lang="{{ LANGUAGE_CODE }}"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE }}" xml:lang="{{ LANGUAGE_CODE }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}> <head> <title>{% block title %}{% endblock %}</title> <link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% load adminmedia %}{% admin_media_prefix %}css/base.css{% endblock %}" /> +{% 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 %} </head> @@ -20,7 +21,7 @@ {% block branding %}{% endblock %} </div> {% if not user.is_anonymous %}{% if user.is_staff %} - <div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name }}{% 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> + <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 %} {% block nav-global %}{% endblock %} </div> diff --git a/django/contrib/admin/templates/admin/filters.html b/django/contrib/admin/templates/admin/filters.html index 93c2f65b15..3ca763cce3 100644 --- a/django/contrib/admin/templates/admin/filters.html +++ b/django/contrib/admin/templates/admin/filters.html @@ -1,6 +1,7 @@ {% load admin_list %} +{% load i18n %} {% if cl.has_filters %}<div id="changelist-filter"> -<h2>Filter</h2> +<h2>{% trans 'Filter' %}</h2> {% for spec in cl.filter_specs %} {% filter cl spec %} {% endfor %}</div>{% endif %} diff --git a/django/contrib/admin/templates/admin/pagination.html b/django/contrib/admin/templates/admin/pagination.html index 64b1b1a3dd..7694e4c5b0 100644 --- a/django/contrib/admin/templates/admin/pagination.html +++ b/django/contrib/admin/templates/admin/pagination.html @@ -1,4 +1,5 @@ {% load admin_list %} +{% load i18n %} <p class="paginator"> {% if pagination_required %} {% for i in page_range %} @@ -6,5 +7,5 @@ {% endfor %} {% endif %} {{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %} -{% if show_all_url %} <a href="{{ show_all_url }}" class="showall">Show all</a>{% endif %} +{% 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/search_form.html b/django/contrib/admin/templates/admin/search_form.html index 24eced9ef9..d9126c3ec5 100644 --- a/django/contrib/admin/templates/admin/search_form.html +++ b/django/contrib/admin/templates/admin/search_form.html @@ -7,7 +7,7 @@ <input type="text" size="40" name="{{ search_var }}" value="{{ cl.query|escape }}" id="searchbar" /> <input type="submit" value="{% trans 'Go' %}" /> {% if show_result_count %} - <span class="small quiet">{{ cl.result_count }} result{{ cl.result_count|pluralize }} (<a href="?">{{ cl.full_result_count }} total</a>)</span> + <span class="small quiet">{% blocktrans count cl.result_count as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?">{% blocktrans with cl.full_result_count as full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span> {% endif %} {% for pair in cl.params.items %} {% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0|escape }}" value="{{ pair.1|escape }}"/>{% endifnotequal %} diff --git a/django/contrib/admin/templates/registration/password_reset_email.html b/django/contrib/admin/templates/registration/password_reset_email.html index b7f31e484c..f765dd0670 100644 --- a/django/contrib/admin/templates/registration/password_reset_email.html +++ b/django/contrib/admin/templates/registration/password_reset_email.html @@ -1,6 +1,6 @@ {% load i18n %} {% trans "You're receiving this e-mail because you requested a password reset" %} -{% trans "for your user account at %(site_name)s" %}. +{% blocktrans %}for your user account at {{ site_name }}{% endblocktrans %}. {% blocktrans %}Your new password is: {{ new_password }}{% endblocktrans %} diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index d5f8df9dfd..0e550dd471 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -131,7 +131,7 @@ def items_for_result(cl, result): if isinstance(f.rel, models.ManyToOneRel): if field_val is not None: - result_repr = getattr(result, f.name) + result_repr = escape(getattr(result, f.name)) else: result_repr = EMPTY_CHANGELIST_VALUE # Dates and times are special: They're formatted in a certain way. diff --git a/django/contrib/admin/templatetags/admin_modify.py b/django/contrib/admin/templatetags/admin_modify.py index 9f646214ce..2d34452f52 100644 --- a/django/contrib/admin/templatetags/admin_modify.py +++ b/django/contrib/admin/templatetags/admin_modify.py @@ -18,6 +18,19 @@ def class_name_to_underscored(name): return '_'.join([s.lower() for s in word_re.findall(name)[:-1]]) def include_admin_script(script_path): + """ + Returns an HTML script element for including a script from the admin + media url. + + Example usage:: + + {% include_admin_script js/calendar.js %} + + could return:: + + <script type="text/javascript" src="/media/admin/js/calendar.js"> + """ + return '<script type="text/javascript" src="%s%s"></script>' % (settings.ADMIN_MEDIA_PREFIX, script_path) include_admin_script = register.simple_tag(include_admin_script) diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index af55587d23..ea7aeb490b 100644 --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -574,7 +574,7 @@ class ChangeList(object): filter_fields = [self.lookup_opts.get_field(field_name) \ for field_name in self.lookup_opts.admin.list_filter] for f in filter_fields: - spec = FilterSpec.create(f, request, self.params) + spec = FilterSpec.create(f, request, self.params, self.model) if spec and spec.has_output(): filter_specs.append(spec) return filter_specs, bool(filter_specs) |