Fixed #32421 -- Made admindocs ModelDetailView show model cached properties.
This commit is contained in:
parent
4372233ebf
commit
dcb094abe8
|
@ -16,6 +16,7 @@ from django.http import Http404
|
||||||
from django.template.engine import Engine
|
from django.template.engine import Engine
|
||||||
from django.urls import get_mod_func, get_resolver, get_urlconf
|
from django.urls import get_mod_func, get_resolver, get_urlconf
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.utils.functional import cached_property
|
||||||
from django.utils.inspect import (
|
from django.utils.inspect import (
|
||||||
func_accepts_kwargs, func_accepts_var_args, get_func_full_args,
|
func_accepts_kwargs, func_accepts_var_args, get_func_full_args,
|
||||||
method_has_no_args,
|
method_has_no_args,
|
||||||
|
@ -250,7 +251,7 @@ class ModelDetailView(BaseAdminDocsView):
|
||||||
methods = []
|
methods = []
|
||||||
# Gather model methods.
|
# Gather model methods.
|
||||||
for func_name, func in model.__dict__.items():
|
for func_name, func in model.__dict__.items():
|
||||||
if inspect.isfunction(func) or isinstance(func, property):
|
if inspect.isfunction(func) or isinstance(func, (cached_property, property)):
|
||||||
try:
|
try:
|
||||||
for exclude in MODEL_METHODS_EXCLUDE:
|
for exclude in MODEL_METHODS_EXCLUDE:
|
||||||
if func_name.startswith(exclude):
|
if func_name.startswith(exclude):
|
||||||
|
@ -261,9 +262,10 @@ class ModelDetailView(BaseAdminDocsView):
|
||||||
verbose = verbose and (
|
verbose = verbose and (
|
||||||
utils.parse_rst(cleandoc(verbose), 'model', _('model:') + opts.model_name)
|
utils.parse_rst(cleandoc(verbose), 'model', _('model:') + opts.model_name)
|
||||||
)
|
)
|
||||||
# Show properties and methods without arguments as fields.
|
# Show properties, cached_properties, and methods without
|
||||||
# Otherwise, show as a 'method with arguments'.
|
# arguments as fields. Otherwise, show as a 'method with
|
||||||
if isinstance(func, property):
|
# arguments'.
|
||||||
|
if isinstance(func, (cached_property, property)):
|
||||||
fields.append({
|
fields.append({
|
||||||
'name': func_name,
|
'name': func_name,
|
||||||
'data_type': get_return_data_type(func_name),
|
'data_type': get_return_data_type(func_name),
|
||||||
|
|
|
@ -55,6 +55,10 @@ system along with all the fields, properties, and methods available on it.
|
||||||
Relationships to other models appear as hyperlinks. Descriptions are pulled
|
Relationships to other models appear as hyperlinks. Descriptions are pulled
|
||||||
from ``help_text`` attributes on fields or from docstrings on model methods.
|
from ``help_text`` attributes on fields or from docstrings on model methods.
|
||||||
|
|
||||||
|
.. versionchanged:: 4.0
|
||||||
|
|
||||||
|
Older versions don't display model cached properties.
|
||||||
|
|
||||||
A model with useful documentation might look like this::
|
A model with useful documentation might look like this::
|
||||||
|
|
||||||
class BlogEntry(models.Model):
|
class BlogEntry(models.Model):
|
||||||
|
|
|
@ -43,6 +43,8 @@ Minor features
|
||||||
* The admindocs now allows esoteric setups where :setting:`ROOT_URLCONF` is not
|
* The admindocs now allows esoteric setups where :setting:`ROOT_URLCONF` is not
|
||||||
a string.
|
a string.
|
||||||
|
|
||||||
|
* The model section of the ``admindocs`` now shows cached properties.
|
||||||
|
|
||||||
:mod:`django.contrib.auth`
|
:mod:`django.contrib.auth`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ Models for testing various aspects of the djang.contrib.admindocs app
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
|
||||||
class Company(models.Model):
|
class Company(models.Model):
|
||||||
|
@ -56,6 +57,10 @@ class Person(models.Model):
|
||||||
def a_property(self):
|
def a_property(self):
|
||||||
return 'a_property'
|
return 'a_property'
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def a_cached_property(self):
|
||||||
|
return 'a_cached_property'
|
||||||
|
|
||||||
def suffix_company_name(self, suffix='ltd'):
|
def suffix_company_name(self, suffix='ltd'):
|
||||||
return self.company.name + suffix
|
return self.company.name + suffix
|
||||||
|
|
||||||
|
|
|
@ -232,6 +232,10 @@ class TestModelDetailView(TestDataMixin, AdminDocsTestCase):
|
||||||
"""Model properties are displayed as fields."""
|
"""Model properties are displayed as fields."""
|
||||||
self.assertContains(self.response, '<td>a_property</td>')
|
self.assertContains(self.response, '<td>a_property</td>')
|
||||||
|
|
||||||
|
def test_instance_of_cached_property_methods_are_displayed(self):
|
||||||
|
"""Model cached properties are displayed as fields."""
|
||||||
|
self.assertContains(self.response, '<td>a_cached_property</td>')
|
||||||
|
|
||||||
def test_method_data_types(self):
|
def test_method_data_types(self):
|
||||||
company = Company.objects.create(name="Django")
|
company = Company.objects.create(name="Django")
|
||||||
person = Person.objects.create(first_name="Human", last_name="User", company=company)
|
person = Person.objects.create(first_name="Human", last_name="User", company=company)
|
||||||
|
|
Loading…
Reference in New Issue