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):