summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhumbertotm <humberto.htm@gmail.com>2018-05-28 19:59:03 -0700
committerTim Graham <timograham@gmail.com>2018-06-03 21:00:28 -0400
commit747ff7a30b79e12d344169200de24f88a22ddee9 (patch)
treec0e40c0ce672866b3d613157d0641dddfa93ce76
parent085ebc5f1a0e96784516e551cb9225cc6836f1d0 (diff)
Fixed #29385 -- Made admindocs ModelDetailView show model properties.
Original patch by bkaluza. Tests and docs by humbertotm.
-rw-r--r--django/contrib/admindocs/views.py14
-rw-r--r--docs/ref/contrib/admin/admindocs.txt10
-rw-r--r--tests/admin_docs/models.py4
-rw-r--r--tests/admin_docs/test_views.py4
4 files changed, 25 insertions, 7 deletions
diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py
index 02449f7401..ac7cd11f1f 100644
--- a/django/contrib/admindocs/views.py
+++ b/django/contrib/admindocs/views.py
@@ -256,7 +256,7 @@ class ModelDetailView(BaseAdminDocsView):
methods = []
# Gather model methods.
for func_name, func in model.__dict__.items():
- if inspect.isfunction(func):
+ if inspect.isfunction(func) or isinstance(func, property):
try:
for exclude in MODEL_METHODS_EXCLUDE:
if func_name.startswith(exclude):
@@ -267,9 +267,15 @@ class ModelDetailView(BaseAdminDocsView):
verbose = verbose and (
utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.model_name)
)
- # If a method has no arguments, show it as a 'field', otherwise
- # as a 'method with arguments'.
- if func_has_no_args(func) and not func_accepts_kwargs(func) and not func_accepts_var_args(func):
+ # Show properties and methods without arguments as fields.
+ # Otherwise, show as a 'method with arguments'.
+ if isinstance(func, property):
+ fields.append({
+ 'name': func_name,
+ 'data_type': get_return_data_type(func_name),
+ 'verbose': verbose or ''
+ })
+ elif func_has_no_args(func) and not func_accepts_kwargs(func) and not func_accepts_var_args(func):
fields.append({
'name': func_name,
'data_type': get_return_data_type(func_name),
diff --git a/docs/ref/contrib/admin/admindocs.txt b/docs/ref/contrib/admin/admindocs.txt
index e519bd8ed1..7779fe822a 100644
--- a/docs/ref/contrib/admin/admindocs.txt
+++ b/docs/ref/contrib/admin/admindocs.txt
@@ -51,9 +51,13 @@ Model reference
===============
The **models** section of the ``admindocs`` page describes each model in the
-system along with all the fields and methods available on it. Relationships
-to other models appear as hyperlinks. Descriptions are pulled from ``help_text``
-attributes on fields or from docstrings on model methods.
+system along with all the fields, properties, and methods available on it.
+Relationships to other models appear as hyperlinks. Descriptions are pulled
+from ``help_text`` attributes on fields or from docstrings on model methods.
+
+.. versionchanged:: 2.2
+
+ Older versions don't display model properties.
A model with useful documentation might look like this::
diff --git a/tests/admin_docs/models.py b/tests/admin_docs/models.py
index a425ae0fcd..02bf1efa9f 100644
--- a/tests/admin_docs/models.py
+++ b/tests/admin_docs/models.py
@@ -52,6 +52,10 @@ class Person(models.Model):
def dummy_function(self, baz, rox, *some_args, **some_kwargs):
return some_kwargs
+ @property
+ def a_property(self):
+ return 'a_property'
+
def suffix_company_name(self, suffix='ltd'):
return self.company.name + suffix
diff --git a/tests/admin_docs/test_views.py b/tests/admin_docs/test_views.py
index c55891a3c0..05e1f6b329 100644
--- a/tests/admin_docs/test_views.py
+++ b/tests/admin_docs/test_views.py
@@ -208,6 +208,10 @@ class TestModelDetailView(TestDataMixin, AdminDocsTestCase):
"""
self.assertContains(self.response, "<td>baz, rox, *some_args, **some_kwargs</td>")
+ def test_instance_of_property_methods_are_displayed(self):
+ """Model properties are displayed as fields."""
+ self.assertContains(self.response, '<td>a_property</td>')
+
def test_method_data_types(self):
company = Company.objects.create(name="Django")
person = Person.objects.create(first_name="Human", last_name="User", company=company)