Package django :: Package contrib :: Package admin :: Package templatetags :: Module admin_list
[hide private]
[frames] | no frames]

Source Code for Module django.contrib.admin.templatetags.admin_list

  1  from django.conf import settings 
  2  from django.contrib.admin.views.main import ALL_VAR, EMPTY_CHANGELIST_VALUE 
  3  from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR 
  4  from django.core.exceptions import ObjectDoesNotExist 
  5  from django.db import models 
  6  from django.utils import dateformat 
  7  from django.utils.html import escape, conditional_escape 
  8  from django.utils.text import capfirst 
  9  from django.utils.safestring import mark_safe 
 10  from django.utils.translation import get_date_formats, get_partial_date_formats, ugettext as _ 
 11  from django.utils.encoding import smart_unicode, smart_str, force_unicode 
 12  from django.template import Library 
 13  import datetime 
 14   
 15  register = Library() 
 16   
 17  DOT = '.' 
 18   
19 -def paginator_number(cl,i):
20 if i == DOT: 21 return u'... ' 22 elif i == cl.page_num: 23 return mark_safe(u'<span class="this-page">%d</span> ' % (i+1)) 24 else: 25 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))
26 paginator_number = register.simple_tag(paginator_number) 27
28 -def pagination(cl):
29 paginator, page_num = cl.paginator, cl.page_num 30 31 pagination_required = (not cl.show_all or not cl.can_show_all) and cl.multi_page 32 if not pagination_required: 33 page_range = [] 34 else: 35 ON_EACH_SIDE = 3 36 ON_ENDS = 2 37 38 # If there are 10 or fewer pages, display links to every page. 39 # Otherwise, do some fancy 40 if paginator.num_pages <= 10: 41 page_range = range(paginator.num_pages) 42 else: 43 # Insert "smart" pagination links, so that there are always ON_ENDS 44 # links at either end of the list of pages, and there are always 45 # ON_EACH_SIDE links at either end of the "current page" link. 46 page_range = [] 47 if page_num > (ON_EACH_SIDE + ON_ENDS): 48 page_range.extend(range(0, ON_EACH_SIDE - 1)) 49 page_range.append(DOT) 50 page_range.extend(range(page_num - ON_EACH_SIDE, page_num + 1)) 51 else: 52 page_range.extend(range(0, page_num + 1)) 53 if page_num < (paginator.num_pages - ON_EACH_SIDE - ON_ENDS - 1): 54 page_range.extend(range(page_num + 1, page_num + ON_EACH_SIDE + 1)) 55 page_range.append(DOT) 56 page_range.extend(range(paginator.num_pages - ON_ENDS, paginator.num_pages)) 57 else: 58 page_range.extend(range(page_num + 1, paginator.num_pages)) 59 60 need_show_all_link = cl.can_show_all and not cl.show_all and cl.multi_page 61 return { 62 'cl': cl, 63 'pagination_required': pagination_required, 64 'show_all_url': need_show_all_link and cl.get_query_string({ALL_VAR: ''}), 65 'page_range': page_range, 66 'ALL_VAR': ALL_VAR, 67 '1': 1, 68 }
69 pagination = register.inclusion_tag('admin/pagination.html')(pagination) 70
71 -def result_headers(cl):
72 lookup_opts = cl.lookup_opts 73 74 for i, field_name in enumerate(lookup_opts.admin.list_display): 75 try: 76 f = lookup_opts.get_field(field_name) 77 admin_order_field = None 78 except models.FieldDoesNotExist: 79 # For non-field list_display values, check for the function 80 # attribute "short_description". If that doesn't exist, fall back 81 # to the method name. And __str__ and __unicode__ are special-cases. 82 if field_name == '__unicode__': 83 header = force_unicode(lookup_opts.verbose_name) 84 elif field_name == '__str__': 85 header = smart_str(lookup_opts.verbose_name) 86 else: 87 attr = getattr(cl.model, field_name) # Let AttributeErrors propagate. 88 try: 89 header = attr.short_description 90 except AttributeError: 91 header = field_name.replace('_', ' ') 92 93 # It is a non-field, but perhaps one that is sortable 94 admin_order_field = getattr(getattr(cl.model, field_name), "admin_order_field", None) 95 if not admin_order_field: 96 yield {"text": header} 97 continue 98 99 # So this _is_ a sortable non-field. Go to the yield 100 # after the else clause. 101 else: 102 if isinstance(f.rel, models.ManyToOneRel) and f.null: 103 yield {"text": f.verbose_name} 104 continue 105 else: 106 header = f.verbose_name 107 108 th_classes = [] 109 new_order_type = 'asc' 110 if field_name == cl.order_field or admin_order_field == cl.order_field: 111 th_classes.append('sorted %sending' % cl.order_type.lower()) 112 new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()] 113 114 yield {"text": header, 115 "sortable": True, 116 "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}), 117 "class_attrib": mark_safe(th_classes and ' class="%s"' % ' '.join(th_classes) or '')}
118
119 -def _boolean_icon(field_val):
120 BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'} 121 return mark_safe(u'<img src="%simg/admin/icon-%s.gif" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val))
122
123 -def items_for_result(cl, result):
124 first = True 125 pk = cl.lookup_opts.pk.attname 126 for field_name in cl.lookup_opts.admin.list_display: 127 row_class = '' 128 try: 129 f = cl.lookup_opts.get_field(field_name) 130 except models.FieldDoesNotExist: 131 # For non-field list_display values, the value is either a method 132 # or a property. 133 try: 134 attr = getattr(result, field_name) 135 allow_tags = getattr(attr, 'allow_tags', False) 136 boolean = getattr(attr, 'boolean', False) 137 if callable(attr): 138 attr = attr() 139 if boolean: 140 allow_tags = True 141 result_repr = _boolean_icon(attr) 142 else: 143 result_repr = smart_unicode(attr) 144 except (AttributeError, ObjectDoesNotExist): 145 result_repr = EMPTY_CHANGELIST_VALUE 146 else: 147 # Strip HTML tags in the resulting text, except if the 148 # function has an "allow_tags" attribute set to True. 149 if not allow_tags: 150 result_repr = escape(result_repr) 151 else: 152 result_repr = mark_safe(result_repr) 153 else: 154 field_val = getattr(result, f.attname) 155 156 if isinstance(f.rel, models.ManyToOneRel): 157 if field_val is not None: 158 result_repr = escape(getattr(result, f.name)) 159 else: 160 result_repr = EMPTY_CHANGELIST_VALUE 161 # Dates and times are special: They're formatted in a certain way. 162 elif isinstance(f, models.DateField) or isinstance(f, models.TimeField): 163 if field_val: 164 (date_format, datetime_format, time_format) = get_date_formats() 165 if isinstance(f, models.DateTimeField): 166 result_repr = capfirst(dateformat.format(field_val, datetime_format)) 167 elif isinstance(f, models.TimeField): 168 result_repr = capfirst(dateformat.time_format(field_val, time_format)) 169 else: 170 result_repr = capfirst(dateformat.format(field_val, date_format)) 171 else: 172 result_repr = EMPTY_CHANGELIST_VALUE 173 row_class = ' class="nowrap"' 174 # Booleans are special: We use images. 175 elif isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField): 176 result_repr = _boolean_icon(field_val) 177 # DecimalFields are special: Zero-pad the decimals. 178 elif isinstance(f, models.DecimalField): 179 if field_val is not None: 180 result_repr = ('%%.%sf' % f.decimal_places) % field_val 181 else: 182 result_repr = EMPTY_CHANGELIST_VALUE 183 # Fields with choices are special: Use the representation 184 # of the choice. 185 elif f.choices: 186 result_repr = dict(f.choices).get(field_val, EMPTY_CHANGELIST_VALUE) 187 else: 188 result_repr = escape(field_val) 189 if force_unicode(result_repr) == '': 190 result_repr = mark_safe('&nbsp;') 191 # If list_display_links not defined, add the link tag to the first field 192 if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links: 193 table_tag = {True:'th', False:'td'}[first] 194 first = False 195