Djangofmt
June 13, 2026 ยท View on GitHub
A fast, HTML aware, Django template formatter, written in Rust.
Formatting 100k+ lines of HTML across 1.7k+ files from scratch.
Heavily rely on the awesome markup_fmt with some additions to support Django fully.
Table of contents
- Installation
- Usage
- Pre-commit hook
- Configuration
- Editor integration
- Controlling the formatting
- Lint rules
- Known limitations
- Benchmarks
- Shell completions
- Contributing
Installation
djangofmt is available on PyPI.
# With pip
pip install djangofmt
# With uv
uv tool install djangofmt@latest # Install djangofmt globally.
uv add --dev djangofmt # Or add djangofmt to your project.
# With pipx
pipx install djangofmt
Usage
djangofmt . # Format all files in the current directory (and any subdirectories).
djangofmt src/templates # Format all template files in `src/templates`
djangofmt templates/base.html # Format individual files
When given a directory, djangofmt recurses into it and formats all *.html, *.jinja, *.jinja2, and *.j2 files it finds.
It also respects .gitignore files.
Looking for a check mode ?
djangofmt intentionally does not provide a built-in check functionality because CI is too late for a code formatter. We strongly recommend using pre-commit or any IDE "format on save" integration. That being said, you can emulate check capability by chaining with a git diff command like so:
djangofmt .
git diff --exit-code -- '*.html' || (echo "HTML templates are not formatted. Run 'djangofmt' to fix." && exit 1)
Pre-commit hook
See pre-commit for instructions.
Sample .pre-commit-config.yaml:
- repo: https://github.com/UnknownPlatypus/djangofmt-pre-commit
rev: v0.2.10
hooks:
- id: djangofmt
The separate repository enables installation without compiling the Rust code.
By default, the configuration uses pre-commit's files option to detect
all text files in directories named templates. If your templates are stored elsewhere, you can override this behavior
by specifying the desired files in the hook configuration within your .pre-commit-config.yaml file.
.svg files support
djangofmt can format svg files too. It will behave exactly the same way as if they were html files. There is a dedicated pre-commit hook for these:
- repo: https://github.com/UnknownPlatypus/djangofmt-pre-commit
rev: v0.2.10
hooks:
- id: djangofmt-svg
Configuration
Djangofmt can also be configured via a [tool.djangofmt] section in your pyproject.toml:
[tool.djangofmt]
line-length = 120
indent-width = 4
profile = "django"
custom-blocks = ["stage", "flatblock"]
html-void-self-closing = "never"
preserve-unquoted-attrs = false
Djangofmt looks for a pyproject.toml file by traversing directories upward from the current working directory.
The first pyproject.toml found is used. If no file is found or the file doesn't contain a [tool.djangofmt] section, defaults are used.
Djangofmt also reads EditorConfig settings from the nearest .editorconfig file:
root = true
[*]
indent_size = 4
max_line_length = 120
Command-line arguments always take precedence over pyproject.toml settings, which take precedence over .editorconfig settings.
See Controlling the formatting for the behaviour of each option and how to opt into per-node overrides.
Editor integration
See the editor integration guide.
Shell completions
You can generate shell completions for your preferred
shell using the djangofmt completions command.
Usage: djangofmt completions <SHELL>
Arguments:
<SHELL>
The shell to generate the completions for
[possible values: bash, elvish, fish, nushell, powershell, zsh]
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details on how to get started.