Skip to main content

Reusable Django app for rendering Django template comments as HTML comments in DEBUG mode.

Project description

django-render-comments

CI PyPI Python License

Render Django template comments as HTML comments in DEBUG mode.

Overview

This Django app converts Django template comments into HTML comments when DEBUG=True, making them visible in the page source and browser developer tools.

Normally, Django template comments ({# comment #} and {% comment %}...{% endcomment %}) are stripped out during template processing, so they do not appear in the rendered HTML output. With this app installed, these comments are transformed into HTML comments (<!-- comment -->) instead when DEBUG=True, allowing developers to see them directly in the rendered HTML. This is useful for debugging, documentation, and collaboration. When DEBUG=False, comments are stripped and everything inside them is ignored (not parsed) as usual by Django's template engine.

An alternative would be to use HTML comments directly in templates, as these are not stripped by Django, but that approach has some downsides:

  • They are included in the rendered output in production (i.e. when DEBUG=False), increasing the HTML payload size and potentially exposing internal notes, debugging information, or other sensitive information to end users.
  • HTML comments are not ignored by the Django template engine so any content inside them (e.g. <!-- {% if user.is_authenticated %}...{% endif %} -->) will still be processed by the Django template engine, potentially causing errors or unintended behavior (e.g. see this Stack Overflow post).

By using this app, developers can use Django's comment tags for all their comments, and have them visible during development and automatically stripped out in production.

Additional Features

Any comments that should always be hidden (even when DEBUG=True) can be marked with a special !hide marker to ensure they are never rendered in the output HTML.

By default, the content from comments will be shown verbatim in the rendered HTML comment and any tags or filters it includes will be ignored by Django's template engine during processing, matching Django's standard behavior. However, adding a !render marker to the comment overrides this so that template tags and filters in the content are processed.

Installation

pip install django-render-comments

Or with uv:

uv add django-render-comments

Quick Start

In your Django settings.py:

  1. Add to INSTALLED_APPS (optional, for app registry):
INSTALLED_APPS = [
    # ...
    'django_render_comments',
]
  1. Configure template loaders:
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'OPTIONS': {
            'loaders': [
                'django_render_comments.loaders.filesystem.Loader',
                'django_render_comments.loaders.app_directories.Loader',
            ],
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                # ... other context processors
            ],
        },
    },
]

Note: When specifying custom loaders, APP_DIRS must not be set (or be False).

How It Works

Before (Django default)

Template:

<div>
    {# Debug: user={{ user }} #}
    {% comment %}Old navigation{% endcomment %}
    <nav>...</nav>
</div>

Output (comments stripped):

<div>


    <nav>...</nav>
</div>

After (with django-render-comments, DEBUG=True)

Output (comments visible in HTML, template tags appear literally):

<div>
    <!-- Debug: user={{ user }} -->
    <!-- Old navigation -->
    <nav>...</nav>
</div>

Note: Template tags like {{ user }} appear literally in the comment output - they are not processed by Django's template engine. This matches the behavior of Django's native {% comment %} block, which protects its content from being processed.

Configuration

Setting Type Default Description
DEBUG bool False Comments only converted when True
RENDER_COMMENTS_ENABLED bool True Set to False to disable even in DEBUG mode

Disabling the Feature

# settings.py
RENDER_COMMENTS_ENABLED = False  # App will not process comments, even if DEBUG=True.

Comment Syntax Support

Django Syntax Converted To
{# comment #} <!-- comment -->
{% comment %}...{% endcomment %} <!-- ... -->
{% comment "note" %}...{% endcomment %} <!-- [note] ... -->

Hidden Comments

Sometimes you may want to keep a comment out of HTML output, even during development. Use the !hide marker for inline comments or "!hide" note for block comments to ensure they are always stripped.

Syntax

Comment Type Normal (converted to HTML) Hidden (always stripped)
Inline {# comment #} {# !hide comment #}
Block {% comment %}...{% endcomment %} {% comment "!hide" %}...{% endcomment %}
Block with note {% comment "note" %}...{% endcomment %} {% comment "!hide note" %}...{% endcomment %}

Behavior

Condition Normal comments Hidden comments
App installed, DEBUG=True Converted to HTML comment Stripped
App installed, DEBUG=False Stripped Stripped
App NOT installed Stripped Stripped

Example

<div>
    {# !hide TODO: Fix security issue in auth flow #}
    {% comment "!hide" %}
    Internal: This endpoint bypasses rate limiting
    {% endcomment %}
    {% comment "!hide todo - fix auth" %}
    Temporary workaround for authentication
    {% endcomment %}
    <p>Content</p>
</div>

With DEBUG=True, renders as:

<div>
    <p>Content</p>
</div>

The hidden comments are completely removed from the output.

Comment Content Rendering

By default, any template tags it contains appear literally in the HTML output and are not processed by Django's template engine. This matches how Django's comments normally behave during template rendering.

Example

{# Debug: user={{ user.email }} #}
{% comment %}{% if debug %}show{% endif %}{% endcomment %}

With DEBUG=True, renders as:

<!-- Debug: user={{ user.email }} -->
<!-- {% if debug %}show{% endif %} -->

Opt-in Processing with !render

For debugging scenarios where you want tags and filters in a comment's content to be processed, for example to see actual variable values, simply add a !render marker to the comment as shown below:

Comment Type Syntax
Inline {# !render user={{ user.name }} #}
Block {% comment "!render" %}{{ value }}{% endcomment %}
Block with note {% comment "!render note" %}{{ value }}{% endcomment %}
Block with dynamic note {% comment "!render {{ var }}" %}{{ value }}{% endcomment %}

Example

{# !render Current user: {{ user.username }} #}
{% comment "!render {{ request.method }}" %}
Request ID: {{ request.id }}
{% endcomment %}

With DEBUG=True and user.username="john", request.method="GET", request.id="abc123", renders as:

<!-- Current user: john -->
<!-- [GET] Request ID: abc123 -->

The !render marker is removed from the output, and template tags are processed (both in the note and in the comment body). Important: Template rendering will only occur when DEBUG=True, so you will usually want to ensure the content does not have side effects outside of the comment (e.g. modifying context variables) that is relied on elsewhere as it will be ignored when DEBUG=False.

Marker Precedence

If both !hide and !render markers are present in a comment (in any order), !hide always takes precedence. The comment will be hidden and no template processing will occur.

{# !hide !render {{ secret }} #}        {# Hidden - !hide wins #}
{# !render !hide {{ secret }} #}        {# Also hidden - !hide still wins #}
{% comment "!render !hide" %}...{% endcomment %}  {# Hidden #}

This ensures that marking a comment as hidden cannot be accidentally bypassed by also adding !render.

Edge Cases & Limitations

  1. Comments in JavaScript strings: Comment patterns inside <script> tags will also be converted. If you have JavaScript containing {# ... #} as string literals, they will be transformed.

  2. Comment patterns in attributes: <div data-info="{# test #}"> will become <div data-info="<!-- test -->">.

  3. Nested HTML comments: If your Django comments contain --, they will be escaped to - - to prevent breaking HTML comment syntax.

  4. Performance: The preprocessing adds minimal overhead as it uses compiled regex patterns and only runs in DEBUG mode.

Requirements

  • Python 3.10+
  • Django 4.2, 5.0, 5.1, 5.2, or 6.0

Development

# Clone the repository
git clone https://github.com/sean-reed/django-render-comments
cd django-render-comments

# Install dependencies
uv sync --group dev

# Run tests (current environment)
uv run pytest

# Run tests with coverage
uv run pytest --cov

# Run full test matrix (Python 3.10-3.13 x Django 4.2-6.0)
uv run nox

# Run specific Python/Django combination
uv run nox -s "tests-3.10(django='4.2')"

# Run linting
uv run nox -s lint

# Run type checking
uv run nox -s typecheck

# List all available test sessions
uv run nox --list

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_render_comments-0.1.0.tar.gz (50.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_render_comments-0.1.0-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file django_render_comments-0.1.0.tar.gz.

File metadata

  • Download URL: django_render_comments-0.1.0.tar.gz
  • Upload date:
  • Size: 50.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for django_render_comments-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8a77b78f3f59c80d50d6c64670c65599aff215a4d75ed9990834631a2bd3e204
MD5 c498dbee10ffb465d21bd251daa1331e
BLAKE2b-256 89559ba7940b69f5e012622c6f2b01382957521646402c9520c541bb1916f398

See more details on using hashes here.

File details

Details for the file django_render_comments-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: django_render_comments-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for django_render_comments-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 87e5122e1bb28ece6ad487c4bd6c583ea58d42ee86102591835418aa2a276e4c
MD5 4619d67c68654e139420a58e46d82dcd
BLAKE2b-256 0ebaf5a10b7e3f7f7755b93a47661ab762f278f2f49f767fe6c7695d65cb9a25

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page