A simple in-app Markdown documentation viewer for Django.
Project description
django-docs-viewer
A simple in-app Markdown documentation viewer for Django.
Point it at a directory of Markdown files and it serves them as browsable documentation pages with an auto-generated sidebar. No build step, no database, no models — pages are read from disk and rendered on request.
Features
- Renders Markdown files (
fenced_code,tables,toc,sane_lists). - Auto-generated sidebar navigation grouped by folder — or hand-written via a
menu.mdfile. - Automatic per-page table of contents built from each page's headings.
- Case-insensitive, traversal-safe URL resolution.
- Serves images referenced from your Markdown.
- Login required by default; can be made public with one setting.
- Self-contained, overridable templates.
How it compares
The niche is zero-build, database-free, self-navigating docs: Markdown rendered at request time, with the sidebar and per-page table of contents built from the folder tree and headings. django-markdown-view also renders at request time but builds no navigation; Django Spellbook builds navigation but via a generation step and as part of a larger Markdown-components framework.
Installation
pip install django-docs-viewer
Usage
Add the app to INSTALLED_APPS and point DOCS_VIEWER_ROOT at your docs
directory:
# settings.py
INSTALLED_APPS = [
# ...
"docs_viewer",
]
DOCS_VIEWER_ROOT = BASE_DIR / "docs"
Include the URLs:
# urls.py
from django.urls import include, path
urlpatterns = [
# ...
path("docs/", include("docs_viewer.urls")),
]
By default the docs require an authenticated user and redirect anonymous
visitors to LOGIN_URL, so make sure your project has a login view — or set
DOCS_VIEWER_LOGIN_REQUIRED = False to make the docs public.
Your docs directory can be flat:
docs/
├── README.md # landing page + site title
├── 01-getting-started.md
└── 02-configuration.md
or nested, with folders becoming sidebar groups:
docs/
├── README.md # landing page + site title
└── manual/
├── 01-getting-started.md
├── 02-configuration.md
└── images/
└── status-legend.png
Folders nest to any depth, and each level becomes a sidebar group, so a subfolder per language keeps translated pages neatly separated instead of listing every language in one flat group:
docs/
├── README.md # landing page + site title
└── manual/
├── deutsch/
│ ├── 01-erste-schritte.md
│ └── 02-konfiguration.md
├── english/
│ ├── 01-getting-started.md
│ └── 02-configuration.md
└── francais/
├── 01-prise-en-main.md
└── 02-configuration.md
Group labels come from the folder name, humanized (dashes and underscores
become spaces, and it is title-cased), so name folders in lowercase — deutsch
renders as Deutsch in the sidebar.
Pages sort by filename within their folder (the index/README first). Prefix
filenames with a zero-padded number (01-, 02-) to control the order; the
prefix is stripped from the sidebar label, so 01-getting-started.md shows as
Getting started. Zero-pad once you pass nine pages, otherwise 10-… sorts
ahead of 2-….
Settings
| Setting | Default | Description |
|---|---|---|
DOCS_VIEWER_ROOT |
(required) | Path to the directory containing your Markdown files. |
DOCS_VIEWER_BASE_TEMPLATE |
"docs_viewer/base.html" |
Template the docs page extends. Point at your own layout. |
DOCS_VIEWER_LOGIN_REQUIRED |
True |
Redirect anonymous users to LOGIN_URL. Set False to make docs public. |
DOCS_VIEWER_TITLE |
"Documentation" |
Fallback page title when no index heading is available. |
DOCS_VIEWER_TOC_DEPTH |
"2-3" |
Heading levels included in the per-page table of contents. |
DOCS_VIEWER_SKIP_DIRS |
["_*"] |
Glob patterns; directories matching any are hidden (excluded from navigation and not served). A custom value replaces the default, so include "_*" if you still want underscore-prefixed directories hidden. |
The page title is taken from the first level-1 heading of the index
(index.md or README.md) at the docs root, falling back to
DOCS_VIEWER_TITLE.
Customizing the template
The docs page (docs_viewer/detail.html) extends whatever template
DOCS_VIEWER_BASE_TEMPLATE names, resolved dynamically at render time. By
default it extends the minimal docs_viewer/base.html bundled with the app, so
it works with no configuration.
To make docs pages inherit your site's chrome, point the setting at your own base template:
DOCS_VIEWER_BASE_TEMPLATE = "myproject/base.html"
Your base template only needs a content block (and, optionally, a title
block):
{% block title %}{% endblock %}
...
{% block content %}{% endblock %}
To change the docs page itself rather than the surrounding layout, override
docs_viewer/detail.html in your own template directory.
Custom navigation
By default the sidebar is generated from your folder tree. To control it by
hand instead, add a menu.md file at the root of your docs directory. When
present, its rendered Markdown replaces the auto-generated sidebar (and
menu.md itself is never served as a page).
Write it as a normal Markdown list of links:
- [Introduction](/docs/)
- [Getting started](/docs/manual/01-getting-started)
- [Configuration](/docs/manual/02-configuration)
The links are rendered as-is, so point them at the paths where you mounted the
viewer — the /docs/ prefix above matches path("docs/", include(...)).
Translations
The interface strings ship translated into English, German and French. The
active language follows Django's usual i18n machinery, so enable
django.middleware.locale.LocaleMiddleware (and keep USE_I18N = True) if you
want the docs to follow the request's language.
Development
poetry install
poetry run python manage.py test tests
Run the full support matrix with tox:
poetry run tox
See CONTRIBUTING.md for coverage, translations, and the pull-request checklist.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_docs_viewer-0.2.0.tar.gz.
File metadata
- Download URL: django_docs_viewer-0.2.0.tar.gz
- Upload date:
- Size: 12.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f90a4e76764c8d69469c61d2c3b8b16dd8cd0fd0df0c7d23a8f5b6b08a7c1a4
|
|
| MD5 |
30161f55cd17f83392a0013fcd1caf5b
|
|
| BLAKE2b-256 |
3276b7f3793a171a1a26293b01b4fa63f41f0830351f3f7d96d31fc64ff3cc21
|
Provenance
The following attestation bundles were made for django_docs_viewer-0.2.0.tar.gz:
Publisher:
publish.yml on JanMalte/django-docs-viewer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_docs_viewer-0.2.0.tar.gz -
Subject digest:
0f90a4e76764c8d69469c61d2c3b8b16dd8cd0fd0df0c7d23a8f5b6b08a7c1a4 - Sigstore transparency entry: 2281741515
- Sigstore integration time:
-
Permalink:
JanMalte/django-docs-viewer@145e09f76d90810cf260060dbd29039199b7cb85 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/JanMalte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@145e09f76d90810cf260060dbd29039199b7cb85 -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_docs_viewer-0.2.0-py3-none-any.whl.
File metadata
- Download URL: django_docs_viewer-0.2.0-py3-none-any.whl
- Upload date:
- Size: 15.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a975c7e0510a74daf9df634b7b510d88bd676145976e5b8282267aaf31aaa49
|
|
| MD5 |
55036b5363940ba3fc74969852d14e83
|
|
| BLAKE2b-256 |
740df02d947703a31bcc1a5aded4b1a1c41023913db5682939d52c72e6f71927
|
Provenance
The following attestation bundles were made for django_docs_viewer-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on JanMalte/django-docs-viewer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_docs_viewer-0.2.0-py3-none-any.whl -
Subject digest:
2a975c7e0510a74daf9df634b7b510d88bd676145976e5b8282267aaf31aaa49 - Sigstore transparency entry: 2281741526
- Sigstore integration time:
-
Permalink:
JanMalte/django-docs-viewer@145e09f76d90810cf260060dbd29039199b7cb85 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/JanMalte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@145e09f76d90810cf260060dbd29039199b7cb85 -
Trigger Event:
push
-
Statement type: