diff options
| author | humbertotm <humberto.htm@gmail.com> | 2018-05-28 19:59:03 -0700 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2018-06-03 21:00:28 -0400 |
| commit | 747ff7a30b79e12d344169200de24f88a22ddee9 (patch) | |
| tree | c0e40c0ce672866b3d613157d0641dddfa93ce76 | |
| parent | 085ebc5f1a0e96784516e551cb9225cc6836f1d0 (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.py | 14 | ||||
| -rw-r--r-- | docs/ref/contrib/admin/admindocs.txt | 10 | ||||
| -rw-r--r-- | tests/admin_docs/models.py | 4 | ||||
| -rw-r--r-- | tests/admin_docs/test_views.py | 4 |
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) |
