summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWiktor Kolodziej <wiktor@pykonik.org>2013-05-21 13:03:45 +0200
committerFlorian Apolloner <florian@apolloner.eu>2013-05-21 13:19:18 +0200
commitcec9558fba1bc6401ea2ec6d71b816b4dfd31b28 (patch)
tree25d82d122f1a3948085baf251f565ec54a029939
parentb1ac241ddc8e496fae9bee5e88511d5698c18ca5 (diff)
Fixed #17308 -- Enabled the use of short_description on properties in the admin.
-rw-r--r--django/contrib/admin/util.py10
-rw-r--r--docs/ref/contrib/admin/index.txt23
-rw-r--r--tests/admin_util/tests.py14
3 files changed, 44 insertions, 3 deletions
diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py
index 97858e688e..078adbe827 100644
--- a/django/contrib/admin/util.py
+++ b/django/contrib/admin/util.py
@@ -269,8 +269,9 @@ def lookup_field(name, obj, model_admin=None):
def label_for_field(name, model, model_admin=None, return_attr=False):
"""
- Returns a sensible label for a field name. The name can be a callable or the
- name of an object attributes, as well as a genuine fields. If return_attr is
+ Returns a sensible label for a field name. The name can be a callable,
+ property (but not created with @property decorator) or the name of an
+ object's attribute, as well as a genuine fields. If return_attr is
True, the resolved attribute (which could be a callable) is also returned.
This will be None if (and only if) the name refers to a field.
"""
@@ -303,6 +304,10 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
if hasattr(attr, "short_description"):
label = attr.short_description
+ elif (isinstance(attr, property) and
+ hasattr(attr, "fget") and
+ hasattr(attr.fget, "short_description")):
+ label = attr.fget.short_description
elif callable(attr):
if attr.__name__ == "<lambda>":
label = "--"
@@ -315,6 +320,7 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
else:
return label
+
def help_text_for_field(name, model):
try:
help_text = model._meta.get_field_by_name(name)[0].help_text
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index 90570f9576..0aec62f7b9 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -464,7 +464,7 @@ subclass::
list_display = ('upper_case_name',)
def upper_case_name(self, obj):
- return ("%s %s" % (obj.first_name, obj.last_name)).upper()
+ return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'
* A string representing an attribute on the model. This behaves almost
@@ -589,6 +589,27 @@ subclass::
The above will tell Django to order by the ``first_name`` field when
trying to sort by ``colored_first_name`` in the admin.
+ * Elements of ``list_display`` can also be properties. Please note however,
+ that due to the way properties work in Python, setting
+ ``short_description`` on a property is only possible when using the
+ ``property()`` function and **not** with the ``@property`` decorator.
+
+ For example::
+
+ class Person(object):
+ first_name = models.CharField(max_length=50)
+ last_name = models.CharField(max_length=50)
+
+ def my_property(self):
+ return self.first_name + ' ' + self.last_name
+ my_property.short_description = "Full name of the person"
+
+ full_name = property(my_property)
+
+ class PersonAdmin(admin.ModelAdmin):
+ list_display = ('full_name',)
+
+
* .. versionadded:: 1.6
The field names in ``list_display`` will also appear as CSS classes in
diff --git a/tests/admin_util/tests.py b/tests/admin_util/tests.py
index 7898f200b5..35b7681cbb 100644
--- a/tests/admin_util/tests.py
+++ b/tests/admin_util/tests.py
@@ -236,6 +236,20 @@ class UtilTests(unittest.TestCase):
("not Really the Model", MockModelAdmin.test_from_model)
)
+ def test_label_for_property(self):
+ # NOTE: cannot use @property decorator, because of
+ # AttributeError: 'property' object has no attribute 'short_description'
+ class MockModelAdmin(object):
+ def my_property(self):
+ return "this if from property"
+ my_property.short_description = 'property short description'
+ test_from_property = property(my_property)
+
+ self.assertEqual(
+ label_for_field("test_from_property", Article, model_admin=MockModelAdmin),
+ 'property short description'
+ )
+
def test_related_name(self):
"""
Regression test for #13963