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 Django template syntax with a style based on the template style guide in Django’s documentation. It does not format HTML or other templated languages.

Djade is fast because it is built in Rust: benchmarked taking 20ms to format 377 templates.

Read more in the introductory post, or below.


Improve your Django and Git skills with my books.


Installation

Use pip:

python -m pip install djade

Python 3.9 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/engine.html
1 file reformatted

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/engine.html
1 file reformatted

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.

--check

Avoid writing any formatted files back. Instead, exit with a non-zero status code if any files would have been modified, and zero otherwise.

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 %}

Django 1.3+: legacy variable assignment syntax

The minimum target Django version is 2.1, so this fixer is always active.

Django 1.3 added support for = to assign variables in {% with %} and {% blocktranslate %} tags. Prior to this, they only supported the legacy syntax using the as keyword, which Django still supports.

Djade rewrites the older as syntax to the newer = one:

-{% with engines.count as total %}
+{% with total=engines.count %}
     ...
 {% endwith %}

-{% blocktranslate with engine.colour as colour %}
+{% blocktranslate with colour=engine.colour %}
     ...
 {% endblocktranslate %}

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.3.1.tar.gz (35.1 kB view details)

Uploaded Source

Built Distributions

djade-1.3.1-py3-none-win_arm64.whl (831.4 kB view details)

Uploaded Python 3 Windows ARM64

djade-1.3.1-py3-none-win_amd64.whl (908.4 kB view details)

Uploaded Python 3 Windows x86-64

djade-1.3.1-py3-none-win32.whl (822.9 kB view details)

Uploaded Python 3 Windows x86

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

Uploaded Python 3 musllinux: musl 1.1+ x86-64

djade-1.3.1-py3-none-musllinux_1_1_aarch64.whl (1.2 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARM64

djade-1.3.1-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.3.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (1.2 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ i686

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

Uploaded Python 3 manylinux: glibc 2.17+ ARMv7l

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

Uploaded Python 3 manylinux: glibc 2.17+ ARM64

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

Uploaded Python 3 macOS 11.0+ ARM64

djade-1.3.1-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.3.1.tar.gz.

File metadata

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

File hashes

Hashes for djade-1.3.1.tar.gz
Algorithm Hash digest
SHA256 f195d76c37e9e84ba42906f96cf50c002cf0eb41861154244af9c73306341f43
MD5 368e3c628a3a38a80bcde09f3a2d6610
BLAKE2b-256 ac12723ed3ae41d5f8eeb7a84e70e003b89f61b9a4429bf9f7aaf7b88d0b9fbf

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for djade-1.3.1-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 5a5843c5129e124fa23979b6cd91b14e8afcad3936c16e4566d170ba01dd25bc
MD5 54b28b714b72f7b25de6a7261e97828d
BLAKE2b-256 169e1f7238277c2dce2ad525c1d6a8641cd2f7c4ea4a9b637b3e1b216f01b0ee

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for djade-1.3.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 818845c802ded818eafc0fb214e7a1a8a35b8e20c59a2d62c1f8afd271c74590
MD5 da5bbe0569d1738091a3b7049e37a49b
BLAKE2b-256 47c11d1ca34ba8f9ec74d40c1bcc1cc005e38560dff222c8fc21b22f8dc34021

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for djade-1.3.1-py3-none-win32.whl
Algorithm Hash digest
SHA256 df0090b2936bdcb29b603f4826eca89cba54995dcf593ccd4cb72e2409dafe38
MD5 771e9c3f7c6064d185e7ce683231e8ff
BLAKE2b-256 b6ed74bb70198bff8055b9e412bb2776223cbe63bcdceac88b9c97e254d879f3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.1-py3-none-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 44d4186e9be5f00ffb69a8e09acff02de0599bb77c0a2f76f962cb72a1a8675f
MD5 34e21cd26e94c8d52808482b7f435e80
BLAKE2b-256 7abd47cad874982b7ebf59217885ab80dfd7b1287f754a9ffa499fff59755577

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.1-py3-none-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 5424c9a2a7a8f983a3c0ca97114498aec00e32babc954919e056a545e399fd53
MD5 8e24a701e8c0810d0c1eed80804ce6bb
BLAKE2b-256 b0d7b183df42e3294d0a5d307466d95a8b74ebacbb0e68b6a8c082e78d2fa347

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6e1aeffd1a8f1457892071759cded2e4b0547fe1d34dc4201aeea4051ebbd254
MD5 903333bbb7ed47fcaab781ba926f61de
BLAKE2b-256 f39c5876282898822ca5cb2adaa8349ff39dffdc8f6449d63818c4d9376c5fd8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 a42d71491ca95632d50c3672fbeca741572388a76dd8a55604651971ec43418a
MD5 a7829356d668283ddc909faf9a5ce0d8
BLAKE2b-256 7e0562eabd2b151b6cf8e391351ce28ac189dc9f048d3327b251fa81b19cd72c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 7a4457fbe5a556772b6704e6d76d76c540782ee735ec281a1dd318b676aab446
MD5 d75c337a18a886bd99f66e51150296b1
BLAKE2b-256 295ddc5654d348073f0629e767e815cda8479b233f327fdf344e04f351718010

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a8327ec570d6835faa282cddaa6c602f0b1da1427407a7132a6ff95c0a860ba9
MD5 307a157868bbde60e6ad82c19e7702b4
BLAKE2b-256 b27c5832feedbe4cff7caa852bb115d5d60f4b1171be7dfa161adc604c120f25

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 78384f27c0a44dd96533edfed38ee70d2cd27cc976611531d7d68f36c95aefd2
MD5 2d23c0211da2f416921e80708d03473a
BLAKE2b-256 882d90af10486c2da9e56e56cd2c68883a9f73bede1a05b9b4872a5136b16005

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 76c281678033fb18fcce96b31d451d40af8ee194148131fb0761eeb88d373c08
MD5 9fafbb6fe5390533155e3d35af26701d
BLAKE2b-256 5436b9c34838a93b3f05276dd77f663009b0c3b71344909755c9e1451dc82630

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