Skip to main content

A Django template formatter.

Project description

https://img.shields.io/github/actions/workflow/status/adamchainz/djade/main.yml.svg?branch=main&style=for-the-badge https://img.shields.io/pypi/v/djade.svg?style=for-the-badge pre-commit
You can have any colour you like, as long as it’s jade.

A Django template formatter.

You can have any colour you like, as long as it’s [d]jade.

Djade formats templates with a style based on the template style guide in Django’s documentation. It’s built in Rust, which makes it fast: benchmarked taking 20ms to format 377 templates.

Read more in the introductory post.


Improve your Django and Git skills with my books.


Installation

Use pip:

python -m pip install djade

Python 3.8 to 3.13 supported.

pre-commit hook

You can also install Djade as a pre-commit hook.

First, add the following to the repos section of your .pre-commit-config.yaml file (docs):

-   repo: https://github.com/adamchainz/djade-pre-commit
    rev: ""  # Replace with the latest tag on GitHub
    hooks:
    -   id: djade
        args: [--target-version, "5.1"]  # Replace with Django version

The separate repository enables installation without compiling the Rust code.

The default configuration uses pre-commit’s files option to pick up all text files in directories called templates (source). You may wish to override this if you have templates in different directories by adding files to the hook configuration in your .pre-commit-config.yaml file.

Second, format your entire project:

pre-commit run djade --all-files

Check these changes for any potential Djade bugs and commit them. Try git diff --ignore-all-space to check non-whitespace changes.

Third, consider adding the previous commit SHA to a .git-blame-ignore-revs file. This will prevent the initial formatting commit from showing up in git blame.

Keep the hook installed to continue formatting your templates. pre-commit’s autoupdate command will upgrade Djade so you can take advantage of future features.

Usage

djade is a command line tool that rewrites files in place. Pass a list of template files to format them:

$ djade --target-version 5.1 templates/**/*.html
Rewriting templates/locomotives/steam_engine.html
Rewriting templates/locomotives/diesel.html

Djade can also upgrade some old template syntax. Add the --target-version option with your Django version as <major>.<minor> to enable applicable fixers:

$ djade --target-version 5.1 templates/**/*.html
Rewriting templates/locomotives/steam_engine.html

Djade does not have any ability to recurse through directories. Use the pre-commit integration, globbing, or another technique to apply it to many files. For example, with git ls-files | xargs:

git ls-files -z -- '*.html' | xargs -0 djade

…or PowerShell’s ForEach-Object:

git ls-files -- '*.html' | %{djade $_}

Options

--target-version

Optional: the version of Django to target, in the format <major>.<minor>. If provided, Djade enables its fixers for versions up to and including the target version. See the list of available versions with djade --help.

Formatting

Djade aims to format Django template syntax in a consistent, clean way. It wants to be like Black: opinionated and free of configuration. Djade’s style is based on the rules listed in the Django contribution style guide’s template style section, plus some more.

Djade does not aim to format the host language of templates (HTML, etc.). That is a much broader scope and hard to do without semantic changes. For example, whitespace is significant in some HTML contexts, such as in <pre> tags, so even adjusting indentation can affect the meaning.

Below are the rules that Djade implements.

Rules from the Django style guide:

  • Single spaces at the start and end of variables and tags:

    -{{train}}
    +{{ train }}
    
    -{%  blow whistle  %}
    +{% blow whistle %}
  • Label {% endblock %} tags that aren’t on the same line as their opening {% block %} tag:

     {% block funnel %}
     ...
    -{% endblock %}
    +{% endblock funnel %}
  • Sort libraries in {% load %} tags:

    -{% load coal boiler %}
    +{% load boiler coal %}
  • Inside variables, no spaces around filters:

    -{{ fire | stoke }}
    +{{ fire|stoke }}
  • Inside tags, single spaces between tokens:

    -{% if  locomotive  ==  'steam engine'  %}
    +{% if locomotive == 'steam engine' %}
  • Unindent top-level {% block %} and {% endblock %} tags when {% extends %} is used:

    -  {% extends 'engine.html' %}
    +{% extends 'engine.html' %}
    
    -  {% block boiler %}
    +{% block boiler %}
       ...
    -  {% endblock boiler %}
    +{% endblock boiler %}

Extra rules:

  • No leading empty lines:

    -
     {% extends 'engine.html' %}
     ...
  • No trailing empty lines:

     ...
     {% endblock wheels %}
    -
    -
  • Single spaces at the start and end of comments:

    -{#choo choo#}
    +{# choo choo #}
  • No labels in {% endblock %} tags on the same line as their opening {% block %} tag:

    -{% block funnel %}...{% endblock funnel %}
    +{% block funnel %}...{% endblock %}
  • Merge consecutive {% load %} tags:

    -{% load boiler %}
    -
    -{% load coal %}
    +{% load boiler coal %}
  • Sort loaded items in {% load ... from .. %} tags:

-{% load steam heat from boiler %}
+{% load heat steam from boiler %}
  • Unindent {% extends %} tags:

    -  {% extends 'engine.html' %}
    +{% extends 'engine.html' %}
  • Exactly one blank line between top-level {% block %} and {% endblock %} tags when {% extends %} is used:

 {% extends 'engine.html' %}

-
 {% block funnel %}
   ...
 {% endblock funnel %}
+
 {% block boiler %}
   ...
 {% endblock boiler %}

Fixers

Djade applies the below fixes based on the target Django version from --target-version.

Django 4.2+: length_is -> length

From the release note:

The length_is template filter is deprecated in favor of length and the == operator within an {% if %} tag.

Djade updates usage of the deprecated filter within if tags, without other conditions, appropriately:

-{% if engines|length_is:1 %}
+{% if engines|length == 1 %}

Django 4.1+: empty ID json_script fixer

From the release note:

The HTML <script> element id attribute is no longer required when wrapping the json_script template filter.

Djade removes the argument where json_script is passed an empty string, to avoid emitting id="":

-{% tracks|json_script:"" %}
+{% tracks|json_script %}

Django 3.1+: trans -> translate, blocktrans / endblocktrans -> blocktranslate / endblocktranslate

From the release note:

The renamed translate and blocktranslate template tags are introduced for internationalization in template code. The older trans and blocktrans template tags aliases continue to work, and will be retained for the foreseeable future.

Djade updates the deprecated tags appropriately:

-{% load blocktrans trans from i18n %}
+{% load blocktranslate translate from i18n %}

-{% trans "Engine colours" %}
+{% translate "Engine colours" %}

-{% blocktrans with colour=engine.colour %}
+{% blocktranslate with colour=engine.colour %}
 This engine is {{ colour }}.
-{% endblocktrans %}
+{% endblocktranslate %}

Django 3.1+: ifequal and ifnotequal -> if

From the release note:

The {% ifequal %} and {% ifnotequal %} template tags are deprecated in favor of {% if %}.

Djade updates the deprecated tags appropriately:

-{% ifequal engine.colour 'blue' %}
+{% if engine.colour == 'blue' %}
 Thomas!
-{% endifequal %}
+{% endif %}

-{% ifnotequal engine.colour 'blue' %}
+{% if engine.colour != 'blue' %}
 Not Thomas.
-{% endifnotequal %}
+{% endif %}

Django 2.1+: admin_static and staticfiles -> static

From the release note:

{% load staticfiles %} and {% load admin_static %} are deprecated in favor of {% load static %}, which works the same.

Djade updates {% load %} tags appropriately:

-{% load staticfiles %}
+{% load static %}

-{% load admin_static %}
+{% load static %}

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

djade-1.1.0.tar.gz (32.0 kB view details)

Uploaded Source

Built Distributions

djade-1.1.0-py3-none-win_arm64.whl (825.6 kB view details)

Uploaded Python 3 Windows ARM64

djade-1.1.0-py3-none-win_amd64.whl (902.2 kB view details)

Uploaded Python 3 Windows x86-64

djade-1.1.0-py3-none-win32.whl (817.4 kB view details)

Uploaded Python 3 Windows x86

djade-1.1.0-py3-none-musllinux_1_1_x86_64.whl (1.2 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ x86-64

djade-1.1.0-py3-none-musllinux_1_1_aarch64.whl (1.1 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARM64

djade-1.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ x86-64

djade-1.1.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (1.2 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ i686

djade-1.1.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.1 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARMv7l

djade-1.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.1 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARM64

djade-1.1.0-py3-none-macosx_11_0_arm64.whl (1.0 MB view details)

Uploaded Python 3 macOS 11.0+ ARM64

djade-1.1.0-py3-none-macosx_10_12_x86_64.whl (1.1 MB view details)

Uploaded Python 3 macOS 10.12+ x86-64

File details

Details for the file djade-1.1.0.tar.gz.

File metadata

  • Download URL: djade-1.1.0.tar.gz
  • Upload date:
  • Size: 32.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for djade-1.1.0.tar.gz
Algorithm Hash digest
SHA256 68f9cf8a604c506d6453043bee499ccf5660b503e48b7ccad4259702f9fcc745
MD5 93714005d425fa9ba33182b5689b615f
BLAKE2b-256 3d5c74caae29277bfed7e60451242b352892d57a60011219d5dab1d9053a3b5d

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-win_arm64.whl.

File metadata

  • Download URL: djade-1.1.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 825.6 kB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for djade-1.1.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 99b6cdf982fec86a480e3c4419cb38c9fad85881818139d76f4123ffbc8a955c
MD5 777975b2cb7341c5bc9e1942f5d882a9
BLAKE2b-256 5e1dd1dd4042c48ba8805a9b48c3ec1814829767a7cb58c3c4241c62eeae9230

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: djade-1.1.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 902.2 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for djade-1.1.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 9c7f050e0496b896969204175d304c2fe232a4f75d0a9cbb5b324e50711630e8
MD5 27c573603701cf7711f9a44e38f07334
BLAKE2b-256 3aa7aa8814a697fc2097674f2f3d7d5729354cb7a1273239f466f64859928444

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-win32.whl.

File metadata

  • Download URL: djade-1.1.0-py3-none-win32.whl
  • Upload date:
  • Size: 817.4 kB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for djade-1.1.0-py3-none-win32.whl
Algorithm Hash digest
SHA256 21c4f37252c5e5ec010eba9f653f0708f24f1f42a7a96db850490d7120c21c6a
MD5 8e020ee354ef87ab20c8030141baa11c
BLAKE2b-256 af991fe3177d2b863331d46ca033266d16dcf22e614ef4b852e4206d080614df

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for djade-1.1.0-py3-none-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 31040c7d9495746e3a953eba9b8991de19a5c11c5d35dc6ca30a31118bcb9ee3
MD5 a4cff3d18a2064426ea2e0baf49508a0
BLAKE2b-256 e702018d818b9ee9b13f1cce1f44a727bce6ab4d5b3875fc6e849c93f9b23e00

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for djade-1.1.0-py3-none-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 aec378be36db53f735a7de0ea87aadeb9a19fc8cd499b0bf5640a4f0757392cd
MD5 0bccdac2ea8415294ae0105b77dc9d9a
BLAKE2b-256 a4a4c6520a17ff49795d75d3e906c263d2ceba785af70ecbdd79e35e130cf214

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for djade-1.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 36643cf355eee64fdb14d890aeaa11dfd3296d8b1b49de6a7b14800dfc4b7a06
MD5 0eb5158ff436b2897fd28e686876fe3c
BLAKE2b-256 f6d7d3b6c73798a697a857cdf48fa47674dacdb0bc93ad5dcf88952e33b3a57a

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for djade-1.1.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e1f9ba6189a257811c026499b4512688efac9c7e6e94d18dddb03f521ebeb548
MD5 6b7122b6959589c9752295967af50166
BLAKE2b-256 8bb85d2ddbe4cc53cf83c74f0c6a2602ec8a90b4b329dc432f636692cee9e3c2

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for djade-1.1.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 8ed22aa1c952f70adf6784d8e552a74cd5866bd34f98ae2902936661cbb16644
MD5 0bfdf87a531bf959430d6549925c5ac8
BLAKE2b-256 859f63d6fbb562d48b1e2bfdf8f0b168bb33bb73eba18e7f479449bd38155e7d

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for djade-1.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 37cd42fb971476a2278557af84b3160021bb515d0df66cd534881bf04239ce4b
MD5 f81758800b0949d3c7f13a1f141a6c70
BLAKE2b-256 ddddd320c38fb7df90041e3107907430a03d8c6c392a18834bcfc6ce65aae238

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for djade-1.1.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4d95feecf48768e2fa9a1379609eb3e7cd36983378e06a106f57a80a9a0831da
MD5 a0c1f7fc4c0df38234408f5c8f8a8ca0
BLAKE2b-256 e38290f41b9cd7b0613c1ddebf2a9c020a633ae4674172854bff33a06f2d69d5

See more details on using hashes here.

File details

Details for the file djade-1.1.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for djade-1.1.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 89fe51129274e897f36e0297a8dd2c80ca8c1aeaea05a5022eee3e385a915088
MD5 9cc010a2b55c0ab32a41f3eb817451b8
BLAKE2b-256 784d17482d80be9dbef4e94e993905accc779d4fea7fdfa5f139c27f711d8d28

See more details on using hashes here.

Supported by

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