Fixed #17308 -- Enabled the use of short_description on properties in the admin.
This commit is contained in:
parent
b1ac241ddc
commit
cec9558fba
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue