summaryrefslogtreecommitdiffstats
path: root/webapp/django/contrib/admin/templatetags/admin_list.py
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/django/contrib/admin/templatetags/admin_list.py')
-rw-r--r--webapp/django/contrib/admin/templatetags/admin_list.py312
1 files changed, 312 insertions, 0 deletions
diff --git a/webapp/django/contrib/admin/templatetags/admin_list.py b/webapp/django/contrib/admin/templatetags/admin_list.py
new file mode 100644
index 0000000000..cae33cc20e
--- /dev/null
+++ b/webapp/django/contrib/admin/templatetags/admin_list.py
@@ -0,0 +1,312 @@
+from django.conf import settings
+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.core.exceptions import ObjectDoesNotExist
+from django.db import models
+from django.utils import dateformat
+from django.utils.html import escape, conditional_escape
+from django.utils.text import capfirst
+from django.utils.safestring import mark_safe
+from django.utils.translation import get_date_formats, get_partial_date_formats, ugettext as _
+from django.utils.encoding import smart_unicode, smart_str, force_unicode
+from django.template import Library
+import datetime
+
+register = Library()
+
+DOT = '.'
+
+def paginator_number(cl,i):
+ if i == DOT:
+ return u'... '
+ elif i == cl.page_num:
+ return mark_safe(u'<span class="this-page">%d</span> ' % (i+1))
+ else:
+ return mark_safe(u'<a href="%s"%s>%d</a> ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.num_pages-1 and ' class="end"' or ''), i+1))
+paginator_number = register.simple_tag(paginator_number)
+
+def pagination(cl):
+ paginator, page_num = cl.paginator, cl.page_num
+
+ pagination_required = (not cl.show_all or not cl.can_show_all) and cl.multi_page
+ if not pagination_required:
+ page_range = []
+ else:
+ ON_EACH_SIDE = 3
+ ON_ENDS = 2
+
+ # If there are 10 or fewer pages, display links to every page.
+ # Otherwise, do some fancy
+ if paginator.num_pages <= 10:
+ page_range = range(paginator.num_pages)
+ else:
+ # Insert "smart" pagination links, so that there are always ON_ENDS
+ # links at either end of the list of pages, and there are always
+ # ON_EACH_SIDE links at either end of the "current page" link.
+ page_range = []
+ if page_num > (ON_EACH_SIDE + ON_ENDS):
+ page_range.extend(range(0, ON_EACH_SIDE - 1))
+ page_range.append(DOT)
+ page_range.extend(range(page_num - ON_EACH_SIDE, page_num + 1))
+ else:
+ page_range.extend(range(0, page_num + 1))
+ if page_num < (paginator.num_pages - ON_EACH_SIDE - ON_ENDS - 1):
+ page_range.extend(range(page_num + 1, page_num + ON_EACH_SIDE + 1))
+ page_range.append(DOT)
+ page_range.extend(range(paginator.num_pages - ON_ENDS, paginator.num_pages))
+ else:
+ page_range.extend(range(page_num + 1, paginator.num_pages))
+
+ need_show_all_link = cl.can_show_all and not cl.show_all and cl.multi_page
+ return {
+ 'cl': cl,
+ 'pagination_required': pagination_required,
+ 'show_all_url': need_show_all_link and cl.get_query_string({ALL_VAR: ''}),
+ 'page_range': page_range,
+ 'ALL_VAR': ALL_VAR,
+ '1': 1,
+ }
+pagination = register.inclusion_tag('admin/pagination.html')(pagination)
+
+def result_headers(cl):
+ lookup_opts = cl.lookup_opts
+
+ for i, field_name in enumerate(cl.list_display):
+ attr = None
+ try:
+ f = lookup_opts.get_field(field_name)
+ admin_order_field = None
+ except models.FieldDoesNotExist:
+ # For non-field list_display values, check for the function
+ # attribute "short_description". If that doesn't exist, fall back
+ # to the method name. And __str__ and __unicode__ are special-cases.
+ if field_name == '__unicode__':
+ header = force_unicode(lookup_opts.verbose_name)
+ elif field_name == '__str__':
+ header = smart_str(lookup_opts.verbose_name)
+ else:
+ if callable(field_name):
+ attr = field_name # field_name can be a callable
+ else:
+ try:
+ attr = getattr(cl.model_admin, field_name)
+ except AttributeError:
+ try:
+ attr = getattr(cl.model, field_name)
+ except AttributeError:
+ raise AttributeError, \
+ "'%s' model or '%s' objects have no attribute '%s'" % \
+ (lookup_opts.object_name, cl.model_admin.__class__, field_name)
+
+ try:
+ header = attr.short_description
+ except AttributeError:
+ if callable(field_name):
+ header = field_name.__name__
+ else:
+ header = field_name
+ header = header.replace('_', ' ')
+
+ # It is a non-field, but perhaps one that is sortable
+ admin_order_field = getattr(attr, "admin_order_field", None)
+ if not admin_order_field:
+ yield {"text": header}
+ continue
+
+ # So this _is_ a sortable non-field. Go to the yield
+ # after the else clause.
+ else:
+ if isinstance(f.rel, models.ManyToOneRel) and f.null:
+ yield {"text": f.verbose_name}
+ continue
+ else:
+ header = f.verbose_name
+
+ th_classes = []
+ new_order_type = 'asc'
+ if field_name == cl.order_field or admin_order_field == cl.order_field:
+ th_classes.append('sorted %sending' % cl.order_type.lower())
+ new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()]
+
+ yield {"text": header,
+ "sortable": True,
+ "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
+ "class_attrib": mark_safe(th_classes and ' class="%s"' % ' '.join(th_classes) or '')}
+
+def _boolean_icon(field_val):
+ BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'}
+ return mark_safe(u'<img src="%simg/admin/icon-%s.gif" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val))
+
+def items_for_result(cl, result):
+ first = True
+ pk = cl.lookup_opts.pk.attname
+ for field_name in cl.list_display:
+ row_class = ''
+ try:
+ f = cl.lookup_opts.get_field(field_name)
+ except models.FieldDoesNotExist:
+ # For non-field list_display values, the value is either a method,
+ # property or returned via a callable.
+ try:
+ if callable(field_name):
+ attr = field_name
+ value = attr(result)
+ elif hasattr(cl.model_admin, field_name) and \
+ not field_name == '__str__' and not field_name == '__unicode__':
+ attr = getattr(cl.model_admin, field_name)
+ value = attr(result)
+ else:
+ attr = getattr(result, field_name)
+ if callable(attr):
+ value = attr()
+ else:
+ value = attr
+ allow_tags = getattr(attr, 'allow_tags', False)
+ boolean = getattr(attr, 'boolean', False)
+ if boolean:
+ allow_tags = True
+ result_repr = _boolean_icon(value)
+ else:
+ result_repr = smart_unicode(value)
+ except (AttributeError, ObjectDoesNotExist):
+ result_repr = EMPTY_CHANGELIST_VALUE
+ else:
+ # Strip HTML tags in the resulting text, except if the
+ # function has an "allow_tags" attribute set to True.
+ if not allow_tags:
+ result_repr = escape(result_repr)
+ else:
+ result_repr = mark_safe(result_repr)
+ else:
+ field_val = getattr(result, f.attname)
+
+ if isinstance(f.rel, models.ManyToOneRel):
+ if field_val is not None:
+ 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.
+ elif isinstance(f, models.DateField) or isinstance(f, models.TimeField):
+ if field_val:
+ (date_format, datetime_format, time_format) = get_date_formats()
+ if isinstance(f, models.DateTimeField):
+ result_repr = capfirst(dateformat.format(field_val, datetime_format))
+ elif isinstance(f, models.TimeField):
+ result_repr = capfirst(dateformat.time_format(field_val, time_format))
+ else:
+ result_repr = capfirst(dateformat.format(field_val, date_format))
+ else:
+ result_repr = EMPTY_CHANGELIST_VALUE
+ row_class = ' class="nowrap"'
+ # Booleans are special: We use images.
+ elif isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField):
+ result_repr = _boolean_icon(field_val)
+ # DecimalFields are special: Zero-pad the decimals.
+ elif isinstance(f, models.DecimalField):
+ if field_val is not None:
+ result_repr = ('%%.%sf' % f.decimal_places) % field_val
+ else:
+ result_repr = EMPTY_CHANGELIST_VALUE
+ # Fields with choices are special: Use the representation
+ # of the choice.
+ elif f.choices:
+ result_repr = dict(f.choices).get(field_val, EMPTY_CHANGELIST_VALUE)
+ else:
+ result_repr = escape(field_val)
+ if force_unicode(result_repr) == '':
+ result_repr = mark_safe('&nbsp;')
+ # If list_display_links not defined, add the link tag to the first field
+ if (first and not cl.list_display_links) or field_name in cl.list_display_links:
+ table_tag = {True:'th', False:'td'}[first]
+ first = False
+ url = cl.url_for_result(result)
+ # Convert the pk to something that can be used in Javascript.
+ # Problem cases are long ints (23L) and non-ASCII strings.
+ result_id = repr(force_unicode(getattr(result, pk)))[1:]
+ yield mark_safe(u'<%s%s><a href="%s"%s>%s</a></%s>' % \
+ (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))
+ else:
+ yield mark_safe(u'<td%s>%s</td>' % (row_class, conditional_escape(result_repr)))
+
+def results(cl):
+ for res in cl.result_list:
+ yield list(items_for_result(cl,res))
+
+def result_list(cl):
+ return {'cl': cl,
+ 'result_headers': list(result_headers(cl)),
+ 'results': list(results(cl))}
+result_list = register.inclusion_tag("admin/change_list_results.html")(result_list)
+
+def date_hierarchy(cl):
+ if cl.date_hierarchy:
+ field_name = cl.date_hierarchy
+ year_field = '%s__year' % field_name
+ month_field = '%s__month' % field_name
+ day_field = '%s__day' % field_name
+ field_generic = '%s__' % field_name
+ year_lookup = cl.params.get(year_field)
+ month_lookup = cl.params.get(month_field)
+ day_lookup = cl.params.get(day_field)
+ year_month_format, month_day_format = get_partial_date_formats()
+
+ link = lambda d: mark_safe(cl.get_query_string(d, [field_generic]))
+
+ if year_lookup and month_lookup and day_lookup:
+ day = datetime.date(int(year_lookup), int(month_lookup), int(day_lookup))
+ return {
+ 'show': True,
+ 'back': {
+ 'link': link({year_field: year_lookup, month_field: month_lookup}),
+ 'title': dateformat.format(day, year_month_format)
+ },
+ 'choices': [{'title': dateformat.format(day, month_day_format)}]
+ }
+ elif year_lookup and month_lookup:
+ days = cl.query_set.filter(**{year_field: year_lookup, month_field: month_lookup}).dates(field_name, 'day')
+ return {
+ 'show': True,
+ 'back': {
+ 'link': link({year_field: year_lookup}),
+ 'title': year_lookup
+ },
+ 'choices': [{
+ 'link': link({year_field: year_lookup, month_field: month_lookup, day_field: day.day}),
+ 'title': dateformat.format(day, month_day_format)
+ } for day in days]
+ }
+ elif year_lookup:
+ months = cl.query_set.filter(**{year_field: year_lookup}).dates(field_name, 'month')
+ return {
+ 'show' : True,
+ 'back': {
+ 'link' : link({}),
+ 'title': _('All dates')
+ },
+ 'choices': [{
+ 'link': link({year_field: year_lookup, month_field: month.month}),
+ 'title': dateformat.format(month, year_month_format)
+ } for month in months]
+ }
+ else:
+ years = cl.query_set.dates(field_name, 'year')
+ return {
+ 'show': True,
+ 'choices': [{
+ 'link': link({year_field: year.year}),
+ 'title': year.year
+ } for year in years]
+ }
+date_hierarchy = register.inclusion_tag('admin/date_hierarchy.html')(date_hierarchy)
+
+def search_form(cl):
+ return {
+ 'cl': cl,
+ 'show_result_count': cl.result_count != cl.full_result_count,
+ 'search_var': SEARCH_VAR
+ }
+search_form = register.inclusion_tag('admin/search_form.html')(search_form)
+
+def admin_list_filter(cl, spec):
+ return {'title': spec.title(), 'choices' : list(spec.choices(cl))}
+admin_list_filter = register.inclusion_tag('admin/filter.html')(admin_list_filter)