In Django, toc_object_entries
is set to False
to disable classes/functions/attributes being added to the page’s table of contents by default (see PR).
Note that toc_object_entries
was a feature added to Sphinx 5.2
This is disabled to avoid duplication in the table of contents in pages such as the SchemaEditor page where headers have been added above each class/method to have them added to the table of contents.
Note, this is what the table of contents look like here when we update toc_object_entries
to True
(the default) without further code changes:
However, Django is not currently consistent with adding headers for each class/method/function/attribute. For example, see the Paginator
docs
In general, the docs are inconsistent with some pages having headers and some not.
I think we should have the classes/functions/methods etc appear in the table of contents consistently for two reasons:
- it improves the on page navigation experience
- the table of contents is used in djangoproject.com search ranking and so searches with matches in the table of contents are ranked higher
If we agree, there are two options:
- add the missing headers to any
docs/ref
page and add the practice of having the header be defined above the method/class etc into our documentation contributing guide
- remove the existing headers that duplicate the function/method/class name and set
toc_object_entries
to True
My preference is 2 as it is less code and one less thing a contributor/reviewer needs to remember to do.
If we opt for 1, this might be due to having more control over the header text. If this is the case, we should document the format preference of these headers in the documentation contributing guide.
What do we think?
I seem to (half?) recall @smithdc1 looking at this a while ago…
If we opt for 1, this might be due to having more control over the header text.
I suspect that’s probably the most of it. (But not certain)
I’d definitely ask @timgraham’s thoughts for context/history/insight.
If we set toc_object_entries = True
, is there a way to prevent the class name from being prefixed to each attribute/method in the toc. The BaseDatabaseSchemaEditor
screenshot shows how unwieldy that can appear. I thought the class name would be omitted if the directives omitted them (e.g. .. method:: create_model(model)
[which requires indenting much of the page… and then regular headings in indented text (like “Methods”) don’t appear in the toc] instead of .. method:: BaseDatabaseSchemaEditor/create_model(model)
but as far as I tested, that’s not the case.
I agree that the need to add a redundant header isn’t ideal. On the negative side, I have a feeling this would be a large patch that will either be difficult to backport, or if not backported, will make future backports painful. But now could be the time while there isn’t too much new in 6.0 and 5.1 docs will soon be abandoned for most backports.
This audit seems likely to reveal other inconsistencies, like the fact that Paginator
has some attributes documented under Page.__init__()
(when they corresponding to the parameters) and others under the “Attributes” heading.
Looks like we can set toc_object_entries_show_parents = "hide"
to achieve this.
If I remove the headers in the schema editor page, it then looks like:
[which requires indenting much of the page… and then regular headings in indented text (like “Methods”) don’t appear in the toc]
The indenting is a good point. In the SchemaEditor case, the indenting looks alright because as I kept the “Methods” and “Attributes” headings (which then indents the methods/attributes).
On pages where the methods/attributes for classes are indented, the result is how you would expect.
I have a feeling this would be a large patch that will either be difficult to backport, or if not backported, will make future backports painful. But now could be the time while there isn’t too much new in 6.0 and 5.1 docs will soon be abandoned for most backports.
(thank you, these are all good points)
Now that I’ve seen the “Methods”/“Attributes” headers, I feel this could be a way for us to avoid adding indents in the docs but still have reasonable indents in the table of contents for docs pages where the methods/attributes are not already indented. This wouldn’t achieve complete consistency, but it would be a smaller diff, and possibly less disruptive for backports.
Been reflecting and I think the @accessibility team should consult here
Folks who use assistive technologies/screen-readers would have to navigate the page differently if we remove headers (they would navigate via lists/list items instead <dl>
, <dt>
…).
I also think the indents impact where the information is structured in the HTML and we should perhaps get guidance on this.
Hence, I would love the accessibility team to review the options available as to how we can structure the reference docs and advise us on the best result in terms of a good table of contents and a good screen reader experience.
We can then add that to the contributing guide and work towards it. 
1 Like
Note that when thinking about this some more, I had forgotten that of course the table of contents will be available for navigation.
I think having this be accessible is a mixture of djangoproject.com page design (see Use <nav> in the docs page for table of contents, breadcrumbs (prev/next) etc · Issue #1956 · django/djangoproject.com · GitHub) and feedback to Sphinx itself.
In which case, I feel we could procede here removing the titles and updating our default settings.
I’ve set up a few one-off previews of the docs with and without toc_object_entries
, and with a manual change to headings, to make it easier to compare the options:
Reviewing those examples, it seems pretty clear toc_object_entries
is a win, with the caveats already mentioned that sometimes there’s been headings manually added, and the auto-generated TOC entry label is very verbose. However, for screen reader users it’s much better if there are actual headings in the content.
With actual headings, they’d be able to:
- Use screen reader support to navigate the page by headings, which is the most common form of navigation as reported by screen reader users.
- More consistently know when a given sub-section starts and how deep they are.
I’m fuzzy on the details but my understanding is most/all of Sphinx’s directives that rely on indentation will output description lists markup (dl
with dt
and dd
), with the description term enhanced to act as a heading (heading styles, anchor link, and now TOC entries). While some usage of description lists is fine, I think it becomes problematic when they get used for overall page sections. They behave like headings for sighted users but come up short for screen reader users.
The issue is pretty clear for example in the Sphinx docs, in The Python Domain. About two thirds of that page’s content have no actual heading elements. For screen reader users the page is reported as having 5 headings, despite there being 67 entries in the table of contents. Those two numbers should probably match in an ideal world.
What to do
My recommendation for Django docs (and any other Sphinx project using those directives):
- See if it’s possible for those directives to create heading levels. If so, check whether it’d be best to do that and description lists markup, or just headings.
- Assuming that’s not possible / in the meantime, switch to manually creating headings instead with vanilla reStructuredText.
- If that’s not possible either / in the meantime,
toc_object_entries
. It’s a good improvement but doesn’t solve the screen reader heading navigation problem.
Would love to do that whenever there’s a chance. I’ve not had much luck finding accessibility considerations / discussions in their project before, but can also be due to my lack of familiarity with it. I’m never too sure as far as markup what comes from docutils vs. Sphinx.