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',
    ...
]

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

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

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

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. These fragments then can be included by a normal Django view.

17.2. Integration with the CMS

In the project’s url.py add a URL pattern, which is used as a common entry point for all documentation pages:

from django.conf.urls import url
from cmsplugin_cascade.sphinx.views import SphinxDocsView

urlpatterns = [
    ...
    url(r'^docs/(?P<page>\S+)/$',
        SphinxDocsView.as_view(template_name='path/to/documentation.html'),
        name='documentation',
    ),
    ...
]

In Django’s admin backend, add a page as the starting point for the documentation inside the CMS menu tree. Typically, one would name the page “Documentation” using docs as its slug. If another slug is desired, then change the urlpatterns from above to use that alternative pattern as well.

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

Optionally select Documentation 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 cascade_tags %}
...
{% 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 docs/ slug corresponds 1:1 to the name of the ReST document.

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 when 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.