diff --git a/djadmin2/templates/admin2/bootstrap/model_list.html b/djadmin2/templates/admin2/bootstrap/model_list.html
index 9da5db2..e021a68 100644
--- a/djadmin2/templates/admin2/bootstrap/model_list.html
+++ b/djadmin2/templates/admin2/bootstrap/model_list.html
@@ -71,7 +71,7 @@
{% if forloop.first and attr == "__str__" %}
{{ model_name|capfirst }} |
{% else %}
- {{ attr }} |
+ {{ model|model_attr_verbose_name:attr|capfirst }} |
{% endif%}
{% endfor %}
diff --git a/djadmin2/templatetags/admin2_tags.py b/djadmin2/templatetags/admin2_tags.py
index b54756c..48f45b2 100644
--- a/djadmin2/templatetags/admin2_tags.py
+++ b/djadmin2/templatetags/admin2_tags.py
@@ -1,4 +1,5 @@
from django import template
+from django.db.models.fields import FieldDoesNotExist
register = template.Library()
@@ -37,6 +38,17 @@ def model_verbose_name_plural(obj):
return utils.model_verbose_name_plural(obj)
+@register.filter
+def model_attr_verbose_name(obj, attr):
+ """
+ Returns the verbose name of a model field or method.
+ """
+ try:
+ return utils.model_field_verbose_name(obj, attr)
+ except FieldDoesNotExist:
+ return utils.model_method_verbose_name(obj, attr)
+
+
@register.filter
def formset_visible_fieldlist(formset):
"""
diff --git a/djadmin2/tests/test_admin2tags.py b/djadmin2/tests/test_admin2tags.py
index b51bb87..a2c3cfc 100644
--- a/djadmin2/tests/test_admin2tags.py
+++ b/djadmin2/tests/test_admin2tags.py
@@ -9,6 +9,14 @@ from ..views import IndexView
class TagsTestsModel(models.Model):
+ field1 = models.CharField(max_length=23)
+ field2 = models.CharField('second field', max_length=42)
+
+ def was_published_recently(self):
+ return True
+ was_published_recently.boolean = True
+ was_published_recently.short_description = 'Published recently?'
+
class Meta:
verbose_name = "Tags Test Model"
verbose_name_plural = "Tags Test Models"
@@ -58,6 +66,24 @@ class TagsTests(TestCase):
admin2_tags.model_verbose_name_plural(self.instance)
)
+ def test_model_field_verbose_name_autogenerated(self):
+ self.assertEquals(
+ 'field1',
+ admin2_tags.model_attr_verbose_name(self.instance, 'field1')
+ )
+
+ def test_model_field_verbose_name_overridden(self):
+ self.assertEquals(
+ 'second field',
+ admin2_tags.model_attr_verbose_name(self.instance, 'field2')
+ )
+
+ def test_model_method_verbose_name(self):
+ self.assertEquals(
+ 'Published recently?',
+ admin2_tags.model_attr_verbose_name(self.instance, 'was_published_recently')
+ )
+
def test_formset_visible_fieldlist(self):
formset = TagsTestFormSet()
self.assertEquals(
diff --git a/djadmin2/tests/test_utils.py b/djadmin2/tests/test_utils.py
index 2528592..c4f32c1 100644
--- a/djadmin2/tests/test_utils.py
+++ b/djadmin2/tests/test_utils.py
@@ -7,6 +7,17 @@ from ..views import IndexView
class UtilsTestModel(models.Model):
+ field1 = models.CharField(max_length=23)
+ field2 = models.CharField('second field', max_length=42)
+
+ def simple_method(self):
+ return 42
+
+ def was_published_recently(self):
+ return True
+ was_published_recently.boolean = True
+ was_published_recently.short_description = 'Published recently?'
+
class Meta:
verbose_name = "Utils Test Model"
verbose_name_plural = "Utils Test Models"
@@ -71,6 +82,30 @@ class UtilsTest(TestCase):
utils.model_verbose_name_plural(self.instance)
)
+ def test_model_field_verbose_name_autogenerated(self):
+ self.assertEquals(
+ 'field1',
+ utils.model_field_verbose_name(self.instance, 'field1')
+ )
+
+ def test_model_field_verbose_name_overridden(self):
+ self.assertEquals(
+ 'second field',
+ utils.model_field_verbose_name(self.instance, 'field2')
+ )
+
+ def test_model_method_verbose_name(self):
+ self.assertEquals(
+ 'Published recently?',
+ utils.model_method_verbose_name(self.instance, 'was_published_recently')
+ )
+
+ def test_model_method_verbose_name_fallback(self):
+ self.assertEquals(
+ 'simple_method',
+ utils.model_method_verbose_name(self.instance, 'simple_method')
+ )
+
def test_app_label_as_model_class(self):
self.assertEquals(
UtilsTestModel._meta.app_label,
diff --git a/djadmin2/utils.py b/djadmin2/utils.py
index fd63458..fa34af0 100644
--- a/djadmin2/utils.py
+++ b/djadmin2/utils.py
@@ -41,18 +41,39 @@ def admin2_urlname(view, action):
return 'admin2:%s_%s_%s' % (view.app_label, view.model_name, action)
-def model_verbose_name(obj):
+def model_verbose_name(model):
"""
Returns the verbose name of a model instance or class.
"""
- return model_options(obj).verbose_name
+ return model_options(model).verbose_name
-def model_verbose_name_plural(obj):
+def model_verbose_name_plural(model):
"""
Returns the pluralized verbose name of a model instance or class.
"""
- return model_options(obj).verbose_name_plural
+ return model_options(model).verbose_name_plural
+
+
+def model_field_verbose_name(model, field_name):
+ """
+ Returns the verbose name of a model field.
+ """
+ meta = model_options(model)
+ field = meta.get_field_by_name(field_name)[0]
+ return field.verbose_name
+
+
+def model_method_verbose_name(model, method_name):
+ """
+ Returns the verbose name / short description of a model field.
+ """
+ meta = model_options(model)
+ method = getattr(model, method_name)
+ try:
+ return method.short_description
+ except AttributeError:
+ return method_name
def model_app_label(obj):