17. Integrate Sphinx Documentation

Restructured Text (ReST) is the de facto standard for documenting Python projects and is even widely used outside of this realm, by applications written in other languages. Sphinx is a compiler to generate HTML, Latex, PDF, e-books, etc. out of sources written in ReST.

HTML rendered by Sphinx, typically is rendered as static content by the web server. This makes it difficult to serve documentation, side by side with content from django-CMS, because these are completely different technologies. Furthermore, since Sphinx uses Jinja2 templates, but django-CMS’s internal templatetags are not available for Jinja2, template sharing is not possible.

Therefore djangocms-cascade offers an integration service, which makes it possible to integrate documentation generated by Sphinx, unintrusively inside the menu tree of django-CMS.

17.1. Configuration

To the project’s settings.py, add these options to the configuration directives:

INSTALLED_APPS = [
    ...
    'cmsplugin_cascade',
    'cmsplugin_cascade.sphinx',
    ...
]

CMS_TEMPLATES = [
    ...,
    ('path/to/documentation.html', "Documentation Page"),
    ...
]

SPHINX_DOCS_ROOT = '/path/to/docs/_build/fragments'

Replace 'path/to/documentation.html' with a filename pointing to your documentation root template (see below).

Point SPHINX_DOCS_ROOT onto the directory, into which the HTML page fragments are generated.

17.1.1. Configure Sphinx Builder

Locate the file Makefile inside the docs folder and add another target to it:

fragments:
        $(SPHINXBUILD) -b fragments $(ALLSPHINXOPTS) $(BUILDDIR)/fragments
        @echo
        @echo "Build finished. The HTML fragments are in $(BUILDDIR)/fragments."

Locate the file conf.py and add:

extensions = [
    ...
    'cmsplugin_cascade.sphinx.fragmentsbuilder',
]

By invoking make fragments, Sphinx generates a HTML fragment for each page inside the documentation folder, typically into docs/_build/fragments. Later we use these fragments and include them using a normal Django view.

17.2. Integration with the CMS

In Django’s admin backend, add a page as the starting point for the documentation inside the CMS menu tree. Typically, one would name that page “Documentation” using docs or documentation as its slug.

In the Advanced Settings tab, choose Documentation Page as the template. This settings has been configured using the directive CMS_TEMPLATES, as shown above.

As Application, select Sphinx Documentation from the pull down menu. This attaches the complete documentation tree just below the chosen slug.

Optionally select Documentation Menu from the pull down menu as the Attached menu. It adds a submenu for each main chapter of the documentation. If omitted, only Documentation is added the the CMS menu tree.

17.2.1. The Documentation Template

You must provide a template to be used by the documentation view. This template typically extends a base CMS page template, providing a header, the navigation bar and the footer. In the block, responsible for rendering the main content, add this template code:

{% extends "path/to/base.html" %}
{% load static cascade_tags %}
...
{% block head %}
{{ block.super }}
<link href="{% static 'cascade/sphinx/css/bootstrap-sphinx.css' %}" rel="stylesheet" type="text/css" />
{% endblock %}
...
{% block main-content %}
    {% if page_content %}
        {{ page_content }}
    {% else %}
        {% sphinx_docs_include "index.html" %}
    {% endif %}
{% endblock %}

This Django template now includes the HTML fragments compiled by Sphinx. This allows us to use django-CMS and combine it with Sphinx. In the URL, the part behind the documentation’s slug corresponds 1:1 to the name of the ReST document.

In this example we add a stylesheet to adopt the output to the Bootstrap theme for Sphinx. Depending on your template layout, the way you import this may vary.

17.2.2. Linking onto Documentation Pages

By overriding the Link Plugin with a special target named Documentation, we can even add links onto our documentation pages symbolically. This means, that whenever we open the LinkPlugin editor, an additional target is added. It offers a select box showing all pages from our documentation tree. This prevents us, having to hard code the URL pointing onto the documentation.

This feature has to be configured in the project’s settings.py, by replacing the LinkPlugin with a modified version of itself:

CMSPLUGIN_CASCADE = {
    ...
    'link_plugin_classes': [
        'cmsplugin_cascade.sphinx.link_plugin.SphinxDocsLinkPlugin',
        'cmsplugin_cascade.link.plugin_base.LinkElementMixin',
        'cmsplugin_cascade.sphinx.link_plugin.SphinxDocsLinkForm',
    ],
    ...
}