diff --git a/CHANGES.rst b/CHANGES.rst index 4d56da9..1bb5a2a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,12 @@ Changelog ========= +Unreleased +---------- + +* [ `#39 `_ ] Fix table names of abstract models (`@insspb `__) + + Version 2.3 (2023-04-12) ------------------------ diff --git a/README.rst b/README.rst index 488937c..34d3b80 100644 --- a/README.rst +++ b/README.rst @@ -80,7 +80,9 @@ Optionally, you can include the table names of your models in their docstrings w .. code-block:: python # Include the database table names of Django models - django_show_db_tables = True + django_show_db_tables = True # Boolean, default: False + # Add abstract database tables names (only takes effect if django_show_db_tables is True) + django_show_db_tables_abstract = True # Boolean, default: False Advanced Usage diff --git a/sphinxcontrib_django/docstrings/__init__.py b/sphinxcontrib_django/docstrings/__init__.py index d029968..2cbfba5 100644 --- a/sphinxcontrib_django/docstrings/__init__.py +++ b/sphinxcontrib_django/docstrings/__init__.py @@ -59,8 +59,12 @@ def setup(app): "django_settings", os.environ.get("DJANGO_SETTINGS_MODULE"), True ) + # Django models tables names configuration. # Set default of django_show_db_tables to False app.add_config_value("django_show_db_tables", False, True) + # Set default of django_show_db_tables_abstract to False + app.add_config_value("django_show_db_tables_abstract", False, True) + # Setup Django after config is initialized app.connect("config-inited", setup_django) diff --git a/sphinxcontrib_django/docstrings/classes.py b/sphinxcontrib_django/docstrings/classes.py index 7489244..b971117 100644 --- a/sphinxcontrib_django/docstrings/classes.py +++ b/sphinxcontrib_django/docstrings/classes.py @@ -46,8 +46,7 @@ def improve_model_docstring(app, model, lines): # Add database table name if app.config.django_show_db_tables: - lines.insert(0, "") - lines.insert(0, f"**Database table:** ``{model._meta.db_table}``") + add_db_table_name(app, model, lines) # Get predefined params to exclude them from the automatically inserted params param_offset = len(":param ") @@ -116,6 +115,27 @@ def improve_model_docstring(app, model, lines): lines.append(".. inheritance-diagram::") # pragma: no cover +def add_db_table_name(app, model, lines): + """ + Format and add table name by extension configuration. + + :param app: The Sphinx application object + :type app: ~sphinx.application.Sphinx + + :param model: The instance of the model to document + :type model: ~django.db.models.Model + + :param lines: The docstring lines + :type lines: list [ str ] + """ + if model._meta.abstract and not app.config.django_show_db_tables_abstract: + return + + table_name = None if model._meta.abstract else model._meta.db_table + lines.insert(0, "") + lines.insert(0, f"**Database table:** ``{table_name}``") + + def add_model_parameters(fields, lines, field_docs): """ Add the given fields as model parameter with the ``:param:`` directive diff --git a/tests/test_class_docstrings.py b/tests/test_class_docstrings.py index 3456fe5..9b45bc3 100644 --- a/tests/test_class_docstrings.py +++ b/tests/test_class_docstrings.py @@ -202,6 +202,79 @@ def test_abstract_model(app, do_autodoc): ] +@pytest.mark.sphinx( + "html", testroot="docstrings", confoverrides={"django_show_db_tables": True} +) +def test_abstract_model_with_tables_names_and_ignore_abstract(app, do_autodoc): + actual = do_autodoc(app, "class", "dummy_django_app.models.AbstractModel") + print(actual) + assert list(actual) == [ + "", + ".. py:class:: AbstractModel(*args, **kwargs)", + " :module: dummy_django_app.models", + "", + "", + " Relationship fields:", + "", + " :param simple_model: Simple model", + ( + " :type simple_model: :class:`~django.db.models.ForeignKey` to" + " :class:`~dummy_django_app.models.SimpleModel`" + ), + " :param user: User", + ( + " :type user: :class:`~django.db.models.ForeignKey` to" + " :class:`~django.contrib.auth.models.User`" + ), + " :param foreignkey_self: Foreignkey self", + ( + " :type foreignkey_self: :class:`~django.db.models.ForeignKey` to" + " :class:`~dummy_django_app.models.AbstractModel`" + ), + "", + ] + + +@pytest.mark.sphinx( + "html", + testroot="docstrings", + confoverrides={ + "django_show_db_tables": True, + "django_show_db_tables_abstract": True, + }, +) +def test_abstract_model_with_tables_names_and_abstract_show(app, do_autodoc): + actual = do_autodoc(app, "class", "dummy_django_app.models.AbstractModel") + print(actual) + assert list(actual) == [ + "", + ".. py:class:: AbstractModel(*args, **kwargs)", + " :module: dummy_django_app.models", + "", + " **Database table:** ``None``", + "", + "", + " Relationship fields:", + "", + " :param simple_model: Simple model", + ( + " :type simple_model: :class:`~django.db.models.ForeignKey` to" + " :class:`~dummy_django_app.models.SimpleModel`" + ), + " :param user: User", + ( + " :type user: :class:`~django.db.models.ForeignKey` to" + " :class:`~django.contrib.auth.models.User`" + ), + " :param foreignkey_self: Foreignkey self", + ( + " :type foreignkey_self: :class:`~django.db.models.ForeignKey` to" + " :class:`~dummy_django_app.models.AbstractModel`" + ), + "", + ] + + @pytest.mark.sphinx("html", testroot="docstrings") def test_file_model(app, do_autodoc): actual = do_autodoc(app, "class", "dummy_django_app.models.FileModel")