Changeset 8352
- Timestamp:
- 08/14/08 15:12:19 (11 months ago)
- Files:
-
- django/trunk/django/contrib/admin/templatetags/admin_list.py (modified) (2 diffs)
- django/trunk/django/contrib/admin/validation.py (modified) (1 diff)
- django/trunk/docs/admin.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/contrib/admin/templatetags/admin_list.py
r7967 r8352 85 85 header = smart_str(lookup_opts.verbose_name) 86 86 else: 87 attr = getattr(cl.model, field_name) # Let AttributeErrors propagate. 87 if callable(field_name): 88 attr = field_name # field_name can be a callable 89 else: 90 try: 91 attr = getattr(cl.model_admin, field_name) 92 except AttributeError: 93 try: 94 attr = getattr(cl.model, field_name) 95 except AttributeError: 96 raise AttributeError, \ 97 "'%s' model or '%s' objects have no attribute '%s'" % \ 98 (lookup_opts.object_name, cl.model_admin.__class__, field_name) 99 88 100 try: 89 101 header = attr.short_description 90 102 except AttributeError: 91 header = field_name.replace('_', ' ') 103 if callable(field_name): 104 header = field_name.__name__ 105 else: 106 header = field_name 107 header = header.replace('_', ' ') 92 108 93 109 # 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)110 admin_order_field = getattr(attr, "admin_order_field", None) 95 111 if not admin_order_field: 96 112 yield {"text": header} … … 129 145 f = cl.lookup_opts.get_field(field_name) 130 146 except models.FieldDoesNotExist: 131 # For non-field list_display values, the value is either a method 132 # or a property.147 # For non-field list_display values, the value is either a method, 148 # property or returned via a callable. 133 149 try: 134 attr = getattr(result, field_name) 150 if callable(field_name): 151 attr = field_name 152 value = attr(result) 153 elif hasattr(cl.model_admin, field_name): 154 attr = getattr(cl.model_admin, field_name) 155 value = attr(result) 156 else: 157 attr = getattr(result, field_name) 158 if callable(attr): 159 value = attr() 160 else: 161 value = attr 135 162 allow_tags = getattr(attr, 'allow_tags', False) 136 163 boolean = getattr(attr, 'boolean', False) 137 if callable(attr):138 attr = attr()139 164 if boolean: 140 165 allow_tags = True 141 result_repr = _boolean_icon( attr)142 else: 143 result_repr = smart_unicode( attr)166 result_repr = _boolean_icon(value) 167 else: 168 result_repr = smart_unicode(value) 144 169 except (AttributeError, ObjectDoesNotExist): 145 170 result_repr = EMPTY_CHANGELIST_VALUE django/trunk/django/contrib/admin/validation.py
r8173 r8352 36 36 _check_istuplew('list_display', cls.list_display) 37 37 for idx, field in enumerate(cls.list_display): 38 f = _check_attr_existsw("list_display[%d]" % idx, field) 39 if isinstance(f, models.ManyToManyField): 40 raise ImproperlyConfigured("`%s.list_display[%d]`, `%s` is a " 41 "ManyToManyField which is not supported." 42 % (cls.__name__, idx, field)) 38 if not callable(field): 39 if not hasattr(cls, field): 40 if not hasattr(model, field): 41 try: 42 return opts.get_field(field) 43 except models.FieldDoesNotExist: 44 raise ImproperlyConfigured("%s.list_display[%d], %r is " 45 "not a callable or an attribute of %r or found in the model %r." 46 % (cls.__name__, idx, field, cls.__name__, model._meta.object_name)) 47 f = _check_attr_existsw("list_display[%d]" % idx, field) 48 if isinstance(f, models.ManyToManyField): 49 raise ImproperlyConfigured("`%s.list_display[%d]`, `%s` is a " 50 "ManyToManyField which is not supported." 51 % (cls.__name__, idx, field)) 43 52 44 53 # list_display_links django/trunk/docs/admin.txt
r8324 r8352 202 202 that displays the ``__unicode__()`` representation of each object. 203 203 204 You have four possible values that can be used in ``list_display``: 205 206 * A field of the model. For example:: 207 208 class PersonAdmin(admin.ModelAdmin): 209 list_display = ('first_name', 'last_name') 210 211 * A callable that accepts one parameter for the model instance. For 212 example:: 213 214 def upper_case_name(obj): 215 return "%s %s" % (obj.first_name, obj.last_name).upper() 216 upper_case_name.short_description = 'Name' 217 218 class PersonAdmin(admin.ModelAdmin): 219 list_display = (upper_case_name,) 220 221 * A string representating an attribute on the ``ModelAdmin``. This behaves 222 the same as the callable. For example:: 223 224 class PersonAdmin(admin.ModelAdmin): 225 list_display = ('upper_case_name',) 226 227 def upper_case_name(self, obj): 228 return "%s %s" % (obj.first_name, obj.last_name).upper() 229 upper_case_name.short_description = 'Name' 230 231 * A string representating an attribute on the model. This behaves almost 232 the same as the callable, but ``self`` in this context is the model 233 instance. Here's a full model example:: 234 235 class Person(models.Model): 236 name = models.CharField(max_length=50) 237 birthday = models.DateField() 238 239 def decade_born_in(self): 240 return self.birthday.strftime('%Y')[:3] + "0's" 241 decade_born_in.short_description = 'Birth decade' 242 243 class PersonAdmin(admin.ModelAdmin): 244 list_display = ('name', 'decade_born_in') 245 204 246 A few special cases to note about ``list_display``: 205 247 … … 216 258 display a pretty "on" or "off" icon instead of ``True`` or ``False``. 217 259 218 * If the string given is a method of the model, Django will call it and 219 display the output. This method should have a ``short_description`` 220 function attribute, for use as the header for the field. 221 222 Here's a full example model:: 223 224 class Person(models.Model): 225 name = models.CharField(max_length=50) 226 birthday = models.DateField() 227 228 def decade_born_in(self): 229 return self.birthday.strftime('%Y')[:3] + "0's" 230 decade_born_in.short_description = 'Birth decade' 231 232 class PersonAdmin(admin.ModelAdmin): 233 list_display = ('name', 'decade_born_in') 234 235 * If the string given is a method of the model, Django will HTML-escape the 236 output by default. If you'd rather not escape the output of the method, 237 give the method an ``allow_tags`` attribute whose value is ``True``. 238 260 * If the string given is a method of the model, ``ModelAdmin`` or a 261 callable, Django will HTML-escape the output by default. If you'd rather 262 not escape the output of the method, give the method an ``allow_tags`` 263 attribute whose value is ``True``. 264 239 265 Here's a full example model:: 240 266 … … 251 277 list_display = ('first_name', 'last_name', 'colored_name') 252 278 253 * If the string given is a method of the model that returns True or False 254 Django will display a pretty "on" or "off" icon if you give the method a 255 ``boolean`` attribute whose value is ``True``. 279 * If the string given is a method of the model, ``ModelAdmin`` or a 280 callable that returns True or False Django will display a pretty "on" or 281 "off" icon if you give the method a ``boolean`` attribute whose value is 282 ``True``. 256 283 257 284 Here's a full example model::
