# exc Source: https://django-docutils.git-pull.com/api/exc/ (api_exc)= # `exc` ```{eval-rst} .. automodule:: django_docutils.exc ``` --- # API Reference Source: https://django-docutils.git-pull.com/api/ (api)= # API Reference :::{seealso} {ref}`Quickstart `. ::: ::::{grid} 1 1 2 2 :gutter: 2 2 3 3 :::{grid-item-card} Exceptions :link: exc :link-type: doc Exception definitions for django-docutils. ::: :::{grid-item-card} Views :link: views :link-type: doc `DocutilsView` and response classes. ::: :::{grid-item-card} Lib :link: lib/index :link-type: doc Publisher, roles, directives, writers, and transforms. ::: :::{grid-item-card} Template Engine :link: template :link-type: doc `DocutilsTemplates` backend for Django. ::: :::{grid-item-card} Template Tags :link: templatetags/index :link-type: doc `{% rst %}` tag and `rst` filter internals. ::: :::: ```{toctree} :maxdepth: 1 :hidden: exc views lib/index template templatetags/index ``` --- # Docutils components Source: https://django-docutils.git-pull.com/api/lib/components/ (api_lib_components)= # Docutils components Registry-aware reference for every docutils component django-docutils ships, generated by [sphinx-autodoc-docutils](https://gp-sphinx.git-pull.com/packages/sphinx-autodoc-docutils/). Each entry surfaces the component's registry metadata — a transform's `default_priority`, the writer's resolved translator class, a role's content support — and registers a cross-reference target in the `docutils` domain, so prose anywhere in these docs can link straight to a component: {docutils:writer}`DjangoDocutilsWriter`, {docutils:transform}`CodeTransform`. django-docutils registers nothing with Sphinx itself (no builders, domains, or config values) — it is a Django-side docutils consumer — so the docutils component family below is the complete inventory. ## Writer Full API: {ref}`api_lib_writers`. ```{eval-rst} .. autowriter:: django_docutils.lib.writers.DjangoDocutilsWriter ``` ## Translator The translator's `Overrides` fact lists only the visit/depart handlers the class defines itself — the customizations layered on docutils' HTML5 translator. Full API: {ref}`api_lib_writers`. ```{eval-rst} .. autotranslator:: django_docutils.lib.writers.DjangoDocutilsHTMLTranslator ``` ## Transforms Full API: {ref}`api_lib_transforms_code`, {ref}`api_lib_transforms_toc`, and {ref}`api_lib_sanitize`. ```{eval-rst} .. autotransform:: django_docutils.lib.transforms.code.CodeTransform .. autotransform:: django_docutils.lib.transforms.toc.Contents .. autotransform:: django_docutils.lib.sanitize.SanitizeTransform ``` ## Directives Registered under the name configured in `DJANGO_DOCUTILS_LIB_RST` (`code-block` by default, with `sourcecode` as a common alias) via {func}`django_docutils.lib.directives.code.register_pygments_directive`. Full API: {ref}`api_lib_directives_code`. ```{eval-rst} .. autodirective:: django_docutils.lib.directives.code.CodeBlock ``` ## Roles Role names shown here derive from the callable names; the names actually registered with docutils come from the `roles` mapping in `DJANGO_DOCUTILS_LIB_RST` (for example `gh` for {rst:role}`github`). Full API: {ref}`api_lib_roles`. ```{eval-rst} .. autorole:: django_docutils.lib.roles.email.email_role .. autorole:: django_docutils.lib.roles.file.file_role .. autorole:: django_docutils.lib.roles.file.manifest_role .. autorole:: django_docutils.lib.roles.github.github_role .. autorole:: django_docutils.lib.roles.hackernews.hackernews_role .. autorole:: django_docutils.lib.roles.kbd.kbd_role .. autorole:: django_docutils.lib.roles.leanpub.leanpub_role .. autorole:: django_docutils.lib.roles.pypi.pypi_role .. autorole:: django_docutils.lib.roles.readthedocs.readthedocs_role .. autorole:: django_docutils.lib.roles.twitter.twitter_role .. autorole:: django_docutils.lib.roles.url.url_role .. autorole:: django_docutils.lib.roles.wikipedia.wikipedia_role ``` --- # lib.directives.code Source: https://django-docutils.git-pull.com/api/lib/directives/code/ (api_lib_directives_code)= # `lib.directives.code` :::{seealso} Registry-aware entry: {rst:dir}`codeblock` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.directives.code :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.directives Source: https://django-docutils.git-pull.com/api/lib/directives/ (api_lib_directives)= # `lib.directives` ```{toctree} :maxdepth: 1 code registry ``` ```{eval-rst} .. automodule:: django_docutils.lib.directives :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.directives.registry Source: https://django-docutils.git-pull.com/api/lib/directives/registry/ (api_lib_directives_registry)= # `lib.directives.registry` ```{eval-rst} .. automodule:: django_docutils.lib.directives.registry :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib Source: https://django-docutils.git-pull.com/api/lib/ (api_lib)= # `lib` ```{toctree} :maxdepth: 1 components directives/index metadata/index publisher roles/index sanitize settings text transforms/index utils views writers ``` --- # lib.metadata.extract Source: https://django-docutils.git-pull.com/api/lib/metadata/extract/ (api_lib_metadata_extract)= # `lib.metadata.extract` ```{eval-rst} .. automodule:: django_docutils.lib.metadata.extract :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.metadata Source: https://django-docutils.git-pull.com/api/lib/metadata/ (api_lib_metadata)= # `lib.metadata` ```{toctree} :maxdepth: 1 extract process processors ``` ```{eval-rst} .. automodule:: django_docutils.lib.metadata :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.metadata.process Source: https://django-docutils.git-pull.com/api/lib/metadata/process/ (api_lib_metadata_process)= # `lib.metadata.process` ```{eval-rst} .. automodule:: django_docutils.lib.metadata.process :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.metadata.processors Source: https://django-docutils.git-pull.com/api/lib/metadata/processors/ (api_lib_metadata_processors)= # `lib.metadata.processors` ```{eval-rst} .. automodule:: django_docutils.lib.metadata.processors :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.publisher Source: https://django-docutils.git-pull.com/api/lib/publisher/ (api_lib_publisher)= # `lib.publisher` ```{eval-rst} .. automodule:: django_docutils.lib.publisher :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.common Source: https://django-docutils.git-pull.com/api/lib/roles/common/ (api_lib_roles_common)= # `lib.roles.common` ```{eval-rst} .. automodule:: django_docutils.lib.roles.common :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.email Source: https://django-docutils.git-pull.com/api/lib/roles/email/ (api_lib_roles_email)= # `lib.roles.email` :::{seealso} Registry-aware entry: {rst:role}`email` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.email :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.file Source: https://django-docutils.git-pull.com/api/lib/roles/file/ (api_lib_roles_file)= # `lib.roles.file` :::{seealso} Registry-aware entries: {rst:role}`file` and {rst:role}`manifest` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.file :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.github Source: https://django-docutils.git-pull.com/api/lib/roles/github/ (api_lib_roles_github)= # `lib.roles.github` :::{seealso} Registry-aware entry: {rst:role}`github` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.github :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.hackernews Source: https://django-docutils.git-pull.com/api/lib/roles/hackernews/ (api_lib_roles_hackernews)= # `lib.roles.hackernews` :::{seealso} Registry-aware entry: {rst:role}`hackernews` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.hackernews :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles Source: https://django-docutils.git-pull.com/api/lib/roles/ (api_lib_roles)= # `lib.roles` ## Core ```{toctree} :maxdepth: 1 common registry types ``` ## Custom roles ```{toctree} :maxdepth: 1 email file github hackernews kbd leanpub pypi readthedocs twitter url wikipedia ``` ```{eval-rst} .. automodule:: django_docutils.lib.roles :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.kbd Source: https://django-docutils.git-pull.com/api/lib/roles/kbd/ (api_lib_roles_kbd)= # `lib.roles.kbd` :::{seealso} Registry-aware entry: {rst:role}`kbd` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.kbd :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.leanpub Source: https://django-docutils.git-pull.com/api/lib/roles/leanpub/ (api_lib_roles_leanpub)= # `lib.roles.leanpub` :::{seealso} Registry-aware entry: {rst:role}`leanpub` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.leanpub :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.pypi Source: https://django-docutils.git-pull.com/api/lib/roles/pypi/ (api_lib_roles_pypi)= # `lib.roles.pypi` :::{seealso} Registry-aware entry: {rst:role}`pypi` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.pypi :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.readthedocs Source: https://django-docutils.git-pull.com/api/lib/roles/readthedocs/ (api_lib_roles_readthedocs)= # `lib.roles.readthedocs` :::{seealso} Registry-aware entry: {rst:role}`readthedocs` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.readthedocs :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.registry Source: https://django-docutils.git-pull.com/api/lib/roles/registry/ (api_lib_roles_registry)= # `lib.roles.registry` ```{eval-rst} .. automodule:: django_docutils.lib.roles.registry :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.twitter Source: https://django-docutils.git-pull.com/api/lib/roles/twitter/ (api_lib_roles_twitter)= # `lib.roles.twitter` :::{seealso} Registry-aware entry: {rst:role}`twitter` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.twitter :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.types Source: https://django-docutils.git-pull.com/api/lib/roles/types/ (api_lib_roles_types)= # `lib.roles.types` ```{eval-rst} .. automodule:: django_docutils.lib.roles.types :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.url Source: https://django-docutils.git-pull.com/api/lib/roles/url/ (api_lib_roles_url)= # `lib.roles.url` :::{seealso} Registry-aware entry: {rst:role}`url` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.url :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.wikipedia Source: https://django-docutils.git-pull.com/api/lib/roles/wikipedia/ (api_lib_roles_wikipedia)= # `lib.roles.wikipedia` :::{seealso} Registry-aware entry: {rst:role}`wikipedia` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.roles.wikipedia :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.sanitize Source: https://django-docutils.git-pull.com/api/lib/sanitize/ (api_lib_sanitize)= # `lib.sanitize` :::{seealso} Registry-aware entry: {docutils:transform}`SanitizeTransform` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.sanitize :members: :private-members: :show-inheritance: :undoc-members: :member-order: bysource ``` --- # lib.settings Source: https://django-docutils.git-pull.com/api/lib/settings/ (api_lib_settings)= # `lib.settings` ```{eval-rst} .. automodule:: django_docutils.lib.settings :members: :private-members: :show-inheritance: :undoc-members: :member-order: bysource ``` --- # lib.text Source: https://django-docutils.git-pull.com/api/lib/text/ (api_lib_text)= # `lib.text` ```{eval-rst} .. automodule:: django_docutils.lib.text :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.transforms.code Source: https://django-docutils.git-pull.com/api/lib/transforms/code/ (api_lib_transforms_code)= # `lib.roles.transforms.code` :::{seealso} Registry-aware entry: {docutils:transform}`CodeTransform` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.transforms.code ``` --- # lib.transforms Source: https://django-docutils.git-pull.com/api/lib/transforms/ (api_lib_transforms)= # `lib.transforms` ```{toctree} :maxdepth: 1 code toc ``` ```{eval-rst} .. automodule:: django_docutils.lib.transforms :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.roles.transforms.toc Source: https://django-docutils.git-pull.com/api/lib/transforms/toc/ (api_lib_transforms_toc)= # `lib.roles.transforms.toc` :::{seealso} Registry-aware entry: {docutils:transform}`Contents` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.transforms.toc ``` --- # lib.utils Source: https://django-docutils.git-pull.com/api/lib/utils/ (api_lib_utils)= # `lib.utils` ```{eval-rst} .. automodule:: django_docutils.lib.utils :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.views Source: https://django-docutils.git-pull.com/api/lib/views/ (api_lib_views)= # `lib.views` ```{eval-rst} .. automodule:: django_docutils.lib.views :members: :private-members: :show-inheritance: :member-order: bysource ``` --- # lib.writers Source: https://django-docutils.git-pull.com/api/lib/writers/ (api_lib_writers)= # `lib.writers` :::{seealso} Registry-aware entries: {docutils:writer}`DjangoDocutilsWriter` and {docutils:translator}`DjangoDocutilsHTMLTranslator` in {ref}`api_lib_components`. ::: ```{eval-rst} .. automodule:: django_docutils.lib.writers :members: :private-members: :show-inheritance: :undoc-members: :member-order: bysource ``` --- # template Source: https://django-docutils.git-pull.com/api/template/ (api_template)= # `template` ```{eval-rst} .. automodule:: django_docutils.template ``` --- # templatetags.django_docutils Source: https://django-docutils.git-pull.com/api/templatetags/django_docutils/ (api_templatetags_django_docutils)= # `templatetags.django_docutils` ```{eval-rst} .. automodule:: django_docutils.templatetags.django_docutils ``` --- # templatetags Source: https://django-docutils.git-pull.com/api/templatetags/ (api_templatetags)= # `templatetags` ```{toctree} :maxdepth: 1 django_docutils ``` ```{eval-rst} .. automodule:: django_docutils.templatetags ``` --- # views Source: https://django-docutils.git-pull.com/api/views/ (api_views)= # `views` ```{eval-rst} .. automodule:: django_docutils.views ``` --- # Changelog Source: https://django-docutils.git-pull.com/history/ (history)= ```{include} ../CHANGES ``` --- # django-docutils Source: https://django-docutils.git-pull.com/ (index)= # django-docutils Docutils (reStructuredText) support for Django templates, views, and template engines. ::::{grid} 1 1 2 2 :gutter: 2 2 3 3 :::{grid-item-card} Quickstart :link: quickstart :link-type: doc Install and render your first RST snippet in 5 minutes. ::: :::{grid-item-card} Topics :link: topics/index :link-type: doc Template tags, template filters, class-based views, security, and FAQ. ::: :::{grid-item-card} API Reference :link: api/index :link-type: doc Every public class, function, and exception. ::: :::{grid-item-card} Contributing :link: project/index :link-type: doc Development setup, code style, release process. ::: :::: ## Install ```console $ pip install django-docutils ``` ```console $ uv add django-docutils ``` See [Quickstart](quickstart.md) for configuration and first steps. ## At a glance ```django {% load django_docutils %} {% rst %} Title ===== *reStructuredText* rendered to HTML inside a Django template. {% endrst %} ``` ```{toctree} :hidden: quickstart topics/index api/index project/index history GitHub ``` --- # Code Style Source: https://django-docutils.git-pull.com/project/code-style/ # Code Style ## Formatting django-docutils uses [ruff](https://github.com/astral-sh/ruff) for both linting and formatting. ```console $ uv run ruff format . ``` ```console $ uv run ruff check . --fix --show-fixes ``` ## Type Checking Strict [mypy](https://mypy-lang.org/) with [django-stubs](https://github.com/typeddjango/django-stubs) is enforced across `src/` and `tests/`. ```console $ uv run mypy ``` ## Docstrings Follow [NumPy-style docstrings](https://numpydoc.readthedocs.io/en/latest/format.html) for all public functions and methods. ## Imports - Always include `from __future__ import annotations` at the top of Python files. - Use `import typing as t` and access via namespace: `t.Optional`, `t.Dict`, etc. --- # Development Source: https://django-docutils.git-pull.com/project/contributing/ # Development Install [git](https://git-scm.com/) and [uv](https://github.com/astral-sh/uv). Clone: ```console $ git clone https://github.com/tony/django-docutils.git ``` ```console $ cd django-docutils ``` Install packages: ```console $ uv sync --all-extras --dev ``` ## Running Tests ```console $ uv run pytest ``` Run a single test file: ```console $ uv run pytest tests/test_template.py ``` Watch tests: ```console $ uv run ptw . ``` ## Building Docs ```console $ uv run sphinx-build docs docs/_build ``` Live-reload: ```console $ uv run sphinx-autobuild docs docs/_build ``` --- # Project Source: https://django-docutils.git-pull.com/project/ (project)= # Project Information for contributors and maintainers. ::::{grid} 1 1 2 2 :gutter: 2 2 3 3 :::{grid-item-card} Contributing :link: contributing :link-type: doc Development setup, running tests, submitting PRs. ::: :::{grid-item-card} Code Style :link: code-style :link-type: doc Ruff, mypy, NumPy docstrings, import conventions. ::: :::{grid-item-card} Releasing :link: releasing :link-type: doc Release checklist and version policy. ::: :::: ```{toctree} :hidden: contributing code-style releasing ``` --- # Releasing Source: https://django-docutils.git-pull.com/project/releasing/ # Releasing ## Version Policy django-docutils is pre-1.0. Minor version bumps may include breaking changes. Users should pin to `>=0.x,<0.y`. ## Release Process Releases are triggered by git tags and published to PyPI via trusted publishing. 1. Update `CHANGES` with the release notes 2. Bump version in `src/django_docutils/__about__.py` 3. Commit: ```console $ git commit -m "django-docutils " ``` 4. Tag: ```console $ git tag v ``` 5. Push: ```console $ git push && git push --tags ``` --- # Quickstart Source: https://django-docutils.git-pull.com/quickstart/ (quickstart)= # Quickstart ## Installation For latest official version: ```console $ pip install django-docutils ``` Upgrading: ```console $ pip install --upgrade django-docutils ``` (developmental-releases)= ### Developmental releases New versions of django-docutils are published to PyPI as alpha, beta, or release candidates. In their versions you will see notification like `a1`, `b1`, and `rc1`, respectively. `1.10.0b4` would mean the 4th beta release of `1.10.0` before general availability. - [pip]\: ```console $ pip install --upgrade --pre django-docutils ``` - [pipx]\: ```console $ pipx install --suffix=@next 'django-docutils' --pip-args '\--pre' --force // Usage: django-docutils@next ``` - [uv]\: ```console $ uv add django-docutils --prerelease allow ``` - [uvx]\: ```console $ uvx --from 'django-docutils' --prerelease allow django-docutils ``` via trunk (can break easily): - [pip]\: ```console $ pip install -e git+https://github.com/tony/django-docutils.git#egg=django-docutils ``` - [pipx]\: ```console $ pipx install --suffix=@master 'django-docutils @ git+https://github.com/tony/django-docutils.git@master' --force ``` - [uv]\: ```console $ uv tool install django-docutils --from git+https://github.com/tony/django-docutils.git ``` [pip]: https://pip.pypa.io/en/stable/ [pipx]: https://pypa.github.io/pipx/docs/ [uv]: https://docs.astral.sh/uv/ [uvx]: https://docs.astral.sh/uv/guides/tools/ ## New to reStructuredText? [reStructuredText] is the markup language; [docutils] is the library that parses and renders it. The official [primer][rst-primer] and [quick reference][rst-quickref] cover the syntax; {ref}`what-is-docutils` maps the wider ecosystem (docutils, Sphinx, Markdown), and the {ref}`faq` answers common questions. [reStructuredText]: https://docutils.sourceforge.io/rst.html [docutils]: https://docutils.sourceforge.io/ [rst-primer]: https://docutils.sourceforge.io/docs/user/rst/quickstart.html [rst-quickref]: https://docutils.sourceforge.io/docs/user/rst/quickref.html ## Add the django app Next, add `django_docutils` to your `INSTALLED_APPS` in your settings file: ```python INSTALLED_APPS = [ # ... your default apps, 'django_docutils' ] ``` ## Next steps Integrate docutils to your django site: 1. {ref}`template_tag` 2. {ref}`template_filter` 3. {ref}`class_based_view` 4. {ref}`security` The rendering defaults disable docutils features that are risky on the web; if your site accepts user-authored markup, start with {ref}`security`. --- # Class-based view Source: https://django-docutils.git-pull.com/topics/class_based_view/ (class_based_view)= # Class-based view ## Setup :::{seealso} {ref}`Quickstart ` ::: You can also use a class-based view to render reStructuredText (reST). :::{important} `DocutilsView` and the `DocutilsTemplates` backend use locked-down Docutils defaults. See {ref}`security` before serving user-authored RST or enabling trusted-content overrides. ::: If you want to use reStructuredText as a django template engine, `INSTALLED_APPS` _isn't_ required, instead you add this to your `TEMPLATES` variable in your settings: ```python TEMPLATES = [ # ... Other engines { "NAME": "docutils", "BACKEND": "django_docutils.template.DocutilsTemplates", "DIRS": [], "APP_DIRS": True, } ] ``` ## Introduction to views Now django will be able to scan for .rst files and process them. In your view: ```python from django_docutils.views import DocutilsView class HomeView(DocutilsView): template_name = 'base.html' rst_name = 'home.rst' ``` *yourapp/templates/home.rst*: ````restructuredtext hey --- hi ## A. hows B. it C. going D. today **hi** *hi* ```` *yourapp/templates/base.html*: ```django {{content}} ``` Output: ```html

hey

hi

  1. hows
  2. it
  3. going
  4. today

hi hi

``` :::{admonition} Explore the API - {class}`~django_docutils.views.DocutilsView`, {class}`~django_docutils.views.DocutilsResponse` - {class}`~django_docutils.lib.views.RSTMixin`, {class}`~django_docutils.lib.views.RSTRawView`, {class}`~django_docutils.lib.views.RSTView` - {class}`~django_docutils.template.DocutilsTemplates`, {class}`~django_docutils.template.DocutilsTemplate` ::: --- # FAQ Source: https://django-docutils.git-pull.com/topics/faq/ (faq)= # FAQ ## General New to the ecosystem? {ref}`what-is-docutils` maps docutils, reStructuredText, Sphinx, and Markdown in one page. ### What is reST, RST, reStructuredText? [reStructuredText] is a markup syntax, similar to markdown. Learn it from the official [primer][rst-primer] and [quick reference][rst-quickref]. [rst-primer]: https://docutils.sourceforge.io/docs/user/rst/quickstart.html [rst-quickref]: https://docutils.sourceforge.io/docs/user/rst/quickref.html ### What is docutils? [docutils] is a python package for parsing and publishing markup. The default docutils package supports reStructuredText. It can also parse markdown when a third-party parser such as [myst-docutils] or [myst-parser] is installed — see {ref}`what-is-docutils` for the details. [myst-docutils]: https://pypi.org/project/myst-docutils/ [myst-parser]: https://myst-parser.readthedocs.io/ ## Django Docutils ### Do I need this package to parse reStructuredText in Django? No! [docutils] can always be used directly. This package simply offers template extensions to use docutils in django views. ### What does this package provide? 3 ways to render reStructuredText via docutils in [Django]: 1. {ref}`template_tag` 2. {ref}`template_filter` 3. {ref}`class_based_view` ### Can I copy code from this project to my own? Yes! Go ahead, the project's source is released under the [MIT license] - you are welcome to view the codebase and copy just what you need. [MIT license]: https://github.com/tony/django-docutils/blob/master/LICENSE [docutils]: https://docutils.sourceforge.io/ [reStructuredText]: https://docutils.sourceforge.io/rst.html [Django]: https://docs.djangoproject.com/ --- # Topics Source: https://django-docutils.git-pull.com/topics/ (topics)= # Topics High-level guides covering django-docutils features, configuration, and common patterns. ::::{grid} 1 1 2 2 :gutter: 2 2 3 3 :::{grid-item-card} Template Tag :link: template_tag :link-type: doc Render reStructuredText inside Django templates with `{% rst %}`. ::: :::{grid-item-card} Template Filter :link: template_filter :link-type: doc Use the `rst` filter to convert RST strings to HTML inline. ::: :::{grid-item-card} Class-based View :link: class_based_view :link-type: doc Serve RST-backed pages with `DocutilsView`. ::: :::{grid-item-card} Security :link: security :link-type: doc Understand locked-down defaults and trusted-content opt-ins. ::: :::{grid-item-card} What is docutils? :link: what_is_docutils :link-type: doc Untangle docutils, reStructuredText, Sphinx, and Markdown. ::: :::{grid-item-card} FAQ :link: faq :link-type: doc Common questions about reStructuredText and django-docutils. ::: :::: ```{toctree} :hidden: template_tag template_filter class_based_view security what_is_docutils faq ``` --- # Security Source: https://django-docutils.git-pull.com/topics/security/ (security)= # Security django-docutils renders reStructuredText to HTML and returns that HTML as safe template output. The default renderer is locked down for content that may come from users, editors, uploads, API requests, or other lower-trust sources. These defaults implement the hardening the docutils project recommends for web applications in [Deploying Docutils Securely]. They reduce risk; they do not make untrusted markup safe to render. The riskiest input is dynamic content — reStructuredText (or any markup) that people type into your site themselves, such as comments, profile text, or CMS fields. [Deploying Docutils Securely]: https://docutils.sourceforge.io/docs/howto/security.html ## Default posture Without extra configuration, django-docutils applies these Docutils settings on public rendering paths: ```python { "file_insertion_enabled": False, "raw_enabled": False, "_disable_config": True, "line_length_limit": 10_000, } ``` This disables `.. include::`, `.. raw::`, `.. csv-table:: :file:`, URL-backed file insertion, and local `docutils.conf` overrides. The HTML publisher also removes raw nodes and blocks unsafe URI schemes such as `javascript:`, `data:`, `file:`, and `vbscript:` before output. URIs that cannot be parsed are treated as disallowed instead of failing the render. A `.. meta::` directive that sets `http-equiv=refresh` is removed, since a meta refresh forces navigation regardless of URL scheme. Markup generated by django-docutils itself renders normally. Pygments code blocks and highlighted inline code are marked trusted after package-controlled HTML generation; the `kbd` role renders escaped inline text instead of raw HTML. User-authored `.. raw::` does not render under safe defaults. ## How sanitization runs Sanitization is the final step before HTML is written. Docutils applies every transform first — including any configured through `DJANGO_DOCUTILS_LIB_RST['transforms']` — and django-docutils sanitizes after them. A transform that builds nodes from user content (for example, an autolinker) cannot emit a `javascript:` link or raw HTML that the locked-down default would otherwise strip from source. Library-generated markup is exempt because it is marked trusted at the point of generation, so Pygments code blocks, highlighted inline code, and the `kbd` role survive while user-authored raw markup does not. The sanitizer is available for custom pipelines: call {func}`~django_docutils.lib.sanitize.sanitize_doctree` on a doctree directly, or add {class}`~django_docutils.lib.sanitize.SanitizeTransform` to your own docutils writer's transform list so it runs last. The default allowed URI schemes are: ```python DJANGO_DOCUTILS_LIB_RST = { "allowed_uri_schemes": ["http", "https", "mailto"], } ``` Relative links and fragment links are still allowed. ## Trusted RST opt-in Only enable unsafe Docutils features for trusted static RST that ships with your application or documentation. Do not enable these settings for comments, CMS fields, profile text, uploaded files, or request data. ```python DJANGO_DOCUTILS_LIB_RST = { "allow_unsafe_docutils_settings": True, "docutils": { "raw_enabled": True, "file_insertion_enabled": True, "_disable_config": False, }, } ``` The opt-in flag is deliberate. Setting `raw_enabled=True` or `file_insertion_enabled=True` alone is ignored by the protected public helpers. ## URI schemes Add ordinary safe schemes directly: ```python DJANGO_DOCUTILS_LIB_RST = { "allowed_uri_schemes": ["http", "https", "mailto", "tel"], } ``` Dangerous schemes such as `javascript:`, `data:`, `file:`, and `vbscript:` are ignored unless `allow_unsafe_docutils_settings=True` is also set. Treat that as trusted-content-only configuration. ## Operational advice Keep the normal Django security rules in place — see [Security in Django] for the framework-level picture: - Validate and limit user-submitted RST before rendering it. - Limit request and upload size at the web server or application boundary. - Use a [Content Security Policy] as defense in depth for rendered pages. - Avoid adding extra {func}`mark_safe() ` calls around user content. - Prefer separate trusted and untrusted rendering settings when your app has both static documentation and user-authored content. [Security in Django]: https://docs.djangoproject.com/en/stable/topics/security/ [Content Security Policy]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --- # Template filter Source: https://django-docutils.git-pull.com/topics/template_filter/ (template_filter)= # Template filter ## Setup :::{seealso} {ref}`Quickstart ` ::: Make sure `django_docutils` is added your `INSTALLED_APPS` in your settings file: ```python INSTALLED_APPS = [ # ... your default apps, 'django_docutils' ] ``` ## Using the django filter :::{important} The `rst` filter uses locked-down Docutils defaults. See {ref}`security` before rendering user-authored RST or enabling trusted-content overrides. ::: In your HTML template: ```django {% load django_docutils %} {% filter rst %} # hey # how's it going A. hows B. it C. going D. today **hi** *hi* {% endfilter %} ``` Output: ```html

hey

hi

  1. hows

  2. it

  3. going

  4. today

hi hi

``` :::{admonition} Explore the API - {func}`~django_docutils.templatetags.django_docutils.rst_filter` ::: --- # Template tag Source: https://django-docutils.git-pull.com/topics/template_tag/ (template_tag)= # Template tag ## Setup :::{seealso} {ref}`Quickstart ` ::: Make sure `django_docutils` is added your `INSTALLED_APPS` in your settings file: ```python INSTALLED_APPS = [ # ... your default apps, 'django_docutils' ] ``` ## Using the django tag :::{important} The `{% rst %}` tag uses locked-down Docutils defaults. See {ref}`security` before rendering user-authored RST or enabling trusted-content overrides. ::: In your HTML template: ```django {% load django_docutils %} {% rst %} # hey # how's it going A. hows B. it C. going D. today **hi** *hi* {% endrst %} ``` Output: ```html

hey

hi

  1. hows

  2. it

  3. going

  4. today

hi hi

``` :::{admonition} Explore the API - {func}`~django_docutils.templatetags.django_docutils.rst` ::: --- # What is docutils? Source: https://django-docutils.git-pull.com/topics/what_is_docutils/ (what-is-docutils)= # What is docutils? A field guide to the names you will meet when rendering markup in Django: [docutils], [reStructuredText], [Sphinx], and friends — and where django-docutils fits among them. ## What is reStructuredText? [reStructuredText] (also written *reST*, *RST*, or *rst*) is a plaintext markup language, comparable to Markdown but older and more extensible. The fastest ways in are the official [primer][rst-primer] and the [quick reference][rst-quickref]. ## What is docutils? [docutils] is the Python library that parses reStructuredText and publishes it to other formats. reStructuredText is the language; docutils is the processing system — the parser is one docutils component, the output writers are others. The [docutils documentation][docutils-docs] covers both halves. ## What is Sphinx — and is django-docutils Sphinx? [Sphinx] is a documentation generator built on top of docutils: it adds cross-references, multi-page projects, themes, and extensions, and it renders sites like the [Python documentation](https://docs.python.org/). Its [reStructuredText primer][sphinx-primer] is another good introduction. django-docutils is not Sphinx. It renders RST fragments and pages inside Django templates and views: | Tool | Built on | Use it for | | --------------- | ----------------- | --------------------------------------- | | [docutils] | — | Parsing and rendering single documents | | [Sphinx] | docutils | Documentation sites and books | | [MyST-Parser] | docutils / Sphinx | Markdown in docutils and Sphinx | | django-docutils | docutils + Django | RST inside Django templates and views | ## Can docutils parse Markdown? Yes — since docutils 0.19, with a third-party parser installed: [myst-docutils] (recommended) or [pycmark]. docutils selects them through its `markdown` / `commonmark` parser aliases — see the [docutils configuration reference][docutils-config]. The older [recommonmark](https://pypi.org/project/recommonmark/) wrapper is deprecated and will be removed in docutils 1.0. django-docutils itself renders reStructuredText. To serve [CommonMark](https://commonmark.org/) Markdown in a docutils or Sphinx pipeline, reach for [MyST-Parser]. ## What can docutils output? reStructuredText input can leave docutils in many formats — django-docutils uses the HTML writer family, the rest come with the [docutils CLI tools][docutils-tools] such as `rst2html5`, `rst2latex`, and `rst2man`: | Writer | Output | | ---------------------------- | --------------------------------------- | | `html5` | HTML5 | | `html4css1` | XHTML 1.0 (the `html` default for now) | | `latex2e`, `xetex` | LaTeX / XeTeX, typically en route to PDF | | `manpage` | Unix man pages | | `odf_odt` | OpenDocument text (LibreOffice) | | `s5_html` | S5 HTML slideshows | | `docutils_xml`, `pseudoxml` | Document-tree XML / debugging output | ## Where does django-docutils fit? Your template or view hands RST source to django-docutils — via {ref}`template_tag`, {ref}`template_filter`, or {ref}`class_based_view` — which runs the docutils parser with hardened settings, removes raw nodes and unsafe link targets from the document tree, and returns HTML produced by docutils' HTML writers. Rendering user-authored markup carries risk that configuration can reduce, not remove — see {ref}`security` and docutils' own [security guide][docutils-security]. [docutils]: https://docutils.sourceforge.io/ [docutils-docs]: https://docutils.sourceforge.io/docs/ [docutils-config]: https://docutils.sourceforge.io/docs/user/config.html [docutils-tools]: https://docutils.sourceforge.io/docs/user/tools.html [docutils-security]: https://docutils.sourceforge.io/docs/howto/security.html [reStructuredText]: https://docutils.sourceforge.io/rst.html [rst-primer]: https://docutils.sourceforge.io/docs/user/rst/quickstart.html [rst-quickref]: https://docutils.sourceforge.io/docs/user/rst/quickref.html [Sphinx]: https://www.sphinx-doc.org/ [sphinx-primer]: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html [MyST-Parser]: https://myst-parser.readthedocs.io/ [myst-docutils]: https://pypi.org/project/myst-docutils/ [pycmark]: https://pypi.org/project/pycmark/ ---