Home
A fast, HTML aware, Django template formatter and linter, 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.
- ⚡️ 70-120x faster than existing Django template formatters
- 🐍 Installable via
pip,uvorpipx - 🛡️ A strict HTML aware parser: invalid HTML is reported as an error instead of being silently mangled
- 🎨 Formats CSS in
<style>tags andstyleattributes, and JSON in<script type="application/json"> - 🔧 Lint rules with autofix, for automatic error correction (e.g., automatically sort Tailwind classes)
- 🛠️
pyproject.tomland.editorconfigsupport - ⌨️ Editor integrations, a pre-commit hook and a browser playground
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¶
To run the formatter:
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 (respecting .gitignore files).
To run the linter:
djangofmt check . # Report violations
djangofmt check --fix . # Apply safe fixes, then report what is left
djangofmt check --fix --unsafe-fixes . # Apply all fixes, unsafe ones included
- See Running the linter for rule selection, fixes and suppression comments, or
djangofmt check --helpfor the full list of options. - See Lint rules for the full list of available rules and categories.
Pre-commit hook¶
See pre-commit for instructions.
Sample .pre-commit-config.yaml:
- repo: https://github.com/UnknownPlatypus/djangofmt-pre-commit
# Djangofmt version.
rev: v1.0.0
hooks:
# Run the linter.
- id: djangofmt-check
args: [--fix]
# Run the formatter.
- 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. There is a dedicated pre-commit hook for these:
- repo: https://github.com/UnknownPlatypus/djangofmt-pre-commit
rev: v1.0.0
hooks:
- id: djangofmt-svg
Check mode¶
--check reports the files that would be reformatted without writing anything, exiting with 1 if any would change:
CI is usually too late for a code formatter though: prefer the pre-commit hook above or an IDE "format on save" integration.
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
Lint rules, used by the djangofmt check command, are configured in the nested [tool.djangofmt.lint] section:
[tool.djangofmt.lint]
select = ["category:all"]
ignore = ["category:style"]
preview = true
target-version = "5.2"
fix = true
[tool.djangofmt.lint.per-file-ignores]
"templates/admin/*.html" = ["missing-img-alt"]
target-version is the Django version your templates target. When unset, it comes from the minimum supported Django version in [project] dependencies.
Rules that depend on it stay disabled until it is known.
Every option is documented in the settings reference.
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:
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.